From: xbw Date: Mon, 20 May 2013 07:22:32 +0000 (+0800) Subject: MT6620: add the new driver JB2 V1.0 X-Git-Tag: firefly_0821_release~7070 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=459e3a26c660fb7c86d0ef99fd5ec60475359c3c;p=firefly-linux-kernel-4.4.55.git MT6620: add the new driver JB2 V1.0 --- diff --git a/arch/arm/mach-rk30/include/mach/mtk_wcn_cmb_stub.h b/arch/arm/mach-rk30/include/mach/mtk_wcn_cmb_stub.h index 18682c0d69ec..ec4d5f19524d 100755 --- a/arch/arm/mach-rk30/include/mach/mtk_wcn_cmb_stub.h +++ b/arch/arm/mach-rk30/include/mach/mtk_wcn_cmb_stub.h @@ -1,39 +1,3 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - * - * MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - - /*! \file \brief Declaration of library functions @@ -85,6 +49,55 @@ #ifndef _MTK_WCN_CMB_STUB_H_ #define _MTK_WCN_CMB_STUB_H_ +#include + typedef enum { + COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ + COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ + COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ + COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ + COMBO_AUDIO_STATE_MAX = 4, + } COMBO_AUDIO_STATE; + + typedef enum { + COMBO_FUNC_TYPE_BT = 0, + COMBO_FUNC_TYPE_FM = 1, + COMBO_FUNC_TYPE_GPS = 2, + COMBO_FUNC_TYPE_WIFI = 3, + COMBO_FUNC_TYPE_WMT = 4, + COMBO_FUNC_TYPE_STP = 5, + COMBO_FUNC_TYPE_NUM = 6 + } COMBO_FUNC_TYPE; + + typedef enum { + COMBO_IF_UART = 0, + COMBO_IF_MSDC = 1, + COMBO_IF_MAX, + } COMBO_IF; + + + /****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + + + /* [GeorgeKuo] Stub functions for other kernel built-in modules to call. + * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo. + */ + //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl); + static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) { + //return mt_combo_audio_ctrl_ex(state, 1); + return 0; + } + //extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); + //extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); + + /* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control + * function on/off. + */ + //extern void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on); + //extern int board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on); +//#include jake /******************************************************************************* * C O M P I L E R F L A G S ******************************************************************************** @@ -129,32 +142,6 @@ typedef enum { CMB_STUB_AIF_CTRL_MAX = 2, } CMB_STUB_AIF_CTRL; -#if 1 /* copied from mt_combo.h */ -typedef enum { - COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ - COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ - COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ - COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ - COMBO_AUDIO_STATE_MAX = 4, -} COMBO_AUDIO_STATE; - -typedef enum { - COMBO_FUNC_TYPE_BT = 0, - COMBO_FUNC_TYPE_FM = 1, - COMBO_FUNC_TYPE_GPS = 2, - COMBO_FUNC_TYPE_WIFI = 3, - COMBO_FUNC_TYPE_WMT = 4, - COMBO_FUNC_TYPE_STP = 5, - COMBO_FUNC_TYPE_NUM = 6 -} COMBO_FUNC_TYPE; - -typedef enum { - COMBO_IF_UART = 0, - COMBO_IF_MSDC = 1, - COMBO_IF_MAX, -} COMBO_IF; -#endif - typedef void (*wmt_bgf_eirq_cb)(void); typedef int (*wmt_aif_ctrl_cb)(CMB_STUB_AIF_X, CMB_STUB_AIF_CTRL); typedef void (*wmt_func_ctrl_cb)(unsigned int, unsigned int); @@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ { ******************************************************************************** */ + + /******************************************************************************* * P R I V A T E D A T A ******************************************************************************** */ + + + + /******************************************************************************* * F U N C T I O N D E C L A R A T I O N S ******************************************************************************** @@ -186,28 +179,23 @@ extern int mtk_wcn_cmb_stub_unreg (void); extern int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); -#if 0 /* remove obsolete audio_ctrl APIs. Use stub_aif_ctrl()! */ -/* [GeorgeKuo] Stub functions for other kernel built-in modules to call. - * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo. - */ -extern int mtk_wcn_cmb_stub_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl); -static inline int mtk_wcn_cmb_stub_audio_ctrl(COMBO_AUDIO_STATE state) { - return mtk_wcn_cmb_stub_audio_ctrl_ex(state, 1); -} +// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting +// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat +// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps +#if 0 +extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on); #endif -/* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control - * function on/off. - */ -extern void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on); - -extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); -extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); - /******************************************************************************* * F U N C T I O N S ******************************************************************************** */ + #endif /* _MTK_WCN_CMB_STUB_H_ */ + + + + + diff --git a/arch/arm/mach-rk3188/include/mach/mtk_wcn_cmb_stub.h b/arch/arm/mach-rk3188/include/mach/mtk_wcn_cmb_stub.h old mode 100644 new mode 100755 index 18682c0d69ec..ec4d5f19524d --- a/arch/arm/mach-rk3188/include/mach/mtk_wcn_cmb_stub.h +++ b/arch/arm/mach-rk3188/include/mach/mtk_wcn_cmb_stub.h @@ -1,39 +1,3 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - * - * MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - - /*! \file \brief Declaration of library functions @@ -85,6 +49,55 @@ #ifndef _MTK_WCN_CMB_STUB_H_ #define _MTK_WCN_CMB_STUB_H_ +#include + typedef enum { + COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ + COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ + COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ + COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ + COMBO_AUDIO_STATE_MAX = 4, + } COMBO_AUDIO_STATE; + + typedef enum { + COMBO_FUNC_TYPE_BT = 0, + COMBO_FUNC_TYPE_FM = 1, + COMBO_FUNC_TYPE_GPS = 2, + COMBO_FUNC_TYPE_WIFI = 3, + COMBO_FUNC_TYPE_WMT = 4, + COMBO_FUNC_TYPE_STP = 5, + COMBO_FUNC_TYPE_NUM = 6 + } COMBO_FUNC_TYPE; + + typedef enum { + COMBO_IF_UART = 0, + COMBO_IF_MSDC = 1, + COMBO_IF_MAX, + } COMBO_IF; + + + /****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + + + /* [GeorgeKuo] Stub functions for other kernel built-in modules to call. + * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo. + */ + //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl); + static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) { + //return mt_combo_audio_ctrl_ex(state, 1); + return 0; + } + //extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); + //extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); + + /* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control + * function on/off. + */ + //extern void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on); + //extern int board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on); +//#include jake /******************************************************************************* * C O M P I L E R F L A G S ******************************************************************************** @@ -129,32 +142,6 @@ typedef enum { CMB_STUB_AIF_CTRL_MAX = 2, } CMB_STUB_AIF_CTRL; -#if 1 /* copied from mt_combo.h */ -typedef enum { - COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ - COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ - COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ - COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ - COMBO_AUDIO_STATE_MAX = 4, -} COMBO_AUDIO_STATE; - -typedef enum { - COMBO_FUNC_TYPE_BT = 0, - COMBO_FUNC_TYPE_FM = 1, - COMBO_FUNC_TYPE_GPS = 2, - COMBO_FUNC_TYPE_WIFI = 3, - COMBO_FUNC_TYPE_WMT = 4, - COMBO_FUNC_TYPE_STP = 5, - COMBO_FUNC_TYPE_NUM = 6 -} COMBO_FUNC_TYPE; - -typedef enum { - COMBO_IF_UART = 0, - COMBO_IF_MSDC = 1, - COMBO_IF_MAX, -} COMBO_IF; -#endif - typedef void (*wmt_bgf_eirq_cb)(void); typedef int (*wmt_aif_ctrl_cb)(CMB_STUB_AIF_X, CMB_STUB_AIF_CTRL); typedef void (*wmt_func_ctrl_cb)(unsigned int, unsigned int); @@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ { ******************************************************************************** */ + + /******************************************************************************* * P R I V A T E D A T A ******************************************************************************** */ + + + + /******************************************************************************* * F U N C T I O N D E C L A R A T I O N S ******************************************************************************** @@ -186,28 +179,23 @@ extern int mtk_wcn_cmb_stub_unreg (void); extern int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); -#if 0 /* remove obsolete audio_ctrl APIs. Use stub_aif_ctrl()! */ -/* [GeorgeKuo] Stub functions for other kernel built-in modules to call. - * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo. - */ -extern int mtk_wcn_cmb_stub_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl); -static inline int mtk_wcn_cmb_stub_audio_ctrl(COMBO_AUDIO_STATE state) { - return mtk_wcn_cmb_stub_audio_ctrl_ex(state, 1); -} +// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting +// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat +// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps +#if 0 +extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on); #endif -/* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control - * function on/off. - */ -extern void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on); - -extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); -extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); - /******************************************************************************* * F U N C T I O N S ******************************************************************************** */ + #endif /* _MTK_WCN_CMB_STUB_H_ */ + + + + + diff --git a/drivers/mtk_wcn_combo/Kconfig b/drivers/mtk_wcn_combo/Kconfig new file mode 100755 index 000000000000..d47905fbdfb2 --- /dev/null +++ b/drivers/mtk_wcn_combo/Kconfig @@ -0,0 +1,149 @@ +menu "MediaTek Connectivity Combo Chip Config" + +config MTK_COMBO + bool "MediaTek Connectivity Combo Chip Support" + help + MTK connectivity combo chip driver for MT6620 + +# +# MTK Combo Chip Selection +# +choice + prompt "Select Chip" + depends on MTK_COMBO + +config MTK_COMBO_CHIP_MT6620 + bool "MT6620" + +#config MTK_COMBO_CHIP_MT6628 +# bool "MT6628" +endchoice + +# +# Target Platform Selection +# +config MTK_COMBO_PLAT_PATH + string "Platform folder name" + depends on MTK_COMBO + default "sample" if MTK_COMBO_PLAT_SAMPLE + help + Specify platform folder under common driver platform folder: + mtk_wcn_combo/common/platform/* + +config MTK_COMBO_DRIVER_VERSION_JB2 + depends on MTK_COMBO + bool "MediaTek Connectivity Combo Driver version is JB2 V1.0" + default n + + help + MTK driver V3.1 will use a different configuration about SDIO. + +# +# MTK COMBO Chip Configuration +# +config MTK_COMBO_COMM + depends on MTK_COMBO + tristate "MediaTek Combo Chip Common part driver" + help + MediaTek combo chip common part driver + +#config MTK_COMBO_COMM_PS +# depends on MTK_COMBO_COMM +# bool "Enable PS support" +# default n +# help +# Enable PS support of common UART interface + +config MTK_COMBO_COMM_UART + depends on MTK_COMBO_COMM + tristate "Common interface UART" + help + Use UART for common part interface type + +#config MTK_COMBO_COMM_SDIO +# depends on MTK_COMBO_COMM +# tristate "Common interface SDIO" +# help +# Use SDIO for common part interface type + +config MTK_COMBO_BT + tristate "MediaTek Combo Chip BT driver" + depends on MTK_COMBO + help + MTK BT /dev/stpbt driver for Bluedroid (mtk_stp_bt.ko) + +config MTK_COMBO_BT_HCI + tristate "MediaTek Combo Chip BlueZ driver" + depends on BT && MTK_COMBO + help + MTK BT driver for BlueZ (hci_stp.ko) + +config MTK_COMBO_FM + tristate "MediaTek Combo Chip FM driver" + depends on MTK_COMBO + help + MTK FM /dev/fm driver (mt6620_fm_drv.ko, mtk_fm_priv.ko) + +config MTK_COMBO_WIFI + tristate "MediaTek Combo Chip Wi-Fi support" + depends on MTK_COMBO + depends on MMC + depends on IPV6 + select WIRELESS_EXT + select WEXT_PRIV + help + This module adds support for wireless adapters based on + MTK MT6620 chipset. + + This driver uses the kernel's wireless extensions subsystem. + + If you choose to build a module, it'll be called dhd. Say M if + unsure. + +#config MTK_COMBO_WIFI_FW_PATH +# depends on MTK_COMBO_WIFI +# string "Firmware path" +# default "/system/etc/firmware/WIFI_RAM_CODE" +# help +# Path to the firmware file + +config MTK_COMBO_WIFI_DEBUG + depends on MTK_COMBO_WIFI + bool "Enable debug output from MT6620 driver" + help + Enable debug messages output from MT6620 driver + +config MTK_COMBO_WIFI_PROC + depends on MTK_COMBO_WIFI + bool "Enable procfs support" + help + Enable procfs support. + +#config MTK_WAPI_SUPPORT +# depends on MTK_COMBO_WIFI +# bool "Enable WAPI support in MT6620 driver" +# help +# Enable WAPI support for devices using MT6620 + +choice + prompt "Host Interface" + depends on MTK_COMBO_WIFI + +config MTK_COMBO_WIFI_HIF_SDIO1 + bool "SDIO #1" + depends on MTK_COMBO_WIFI +endchoice + + +config MTK_GPS + tristate "MediaTek GPS Support" + help + MTK GPS /dev/gps driver (mtk_gps.ko) + +config MTK_COMBO_GPS + tristate "MediaTek Combo Chip GPS driver" + depends on MTK_COMBO && MTK_GPS + help + MTK GPS /dev/stpgps driver (mtk_stp_gps.ko) + +endmenu diff --git a/drivers/mtk_wcn_combo/Makefile b/drivers/mtk_wcn_combo/Makefile new file mode 100755 index 000000000000..7d1689039149 --- /dev/null +++ b/drivers/mtk_wcn_combo/Makefile @@ -0,0 +1,60 @@ +# Copyright Statement: +# +# This software/firmware and related documentation ("MediaTek Software") are +# protected under relevant copyright laws. The information contained herein +# is confidential and proprietary to MediaTek Inc. and/or its licensors. +# Without the prior written permission of MediaTek inc. and/or its licensors, +# any reproduction, modification, use or disclosure of MediaTek Software, +# and information contained herein, in whole or in part, shall be strictly prohibited. +# +# MediaTek Inc. (C) 2010. All rights reserved. +# +# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON +# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH +# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES +# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES +# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK +# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR +# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND +# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO +# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +# +# The following software/firmware and/or related documentation ("MediaTek Software") +# have been modified by MediaTek Inc. All revisions are subject to any receiver's +# applicable license agreements with MediaTek Inc. + + +# combo driver: MT6620 +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) + #subdir-ccflags-y can be used in 2.6.34 in the future + #subdir-ccflags-y += -I$(src)/common/include -I$(src)/common/linux/include + #used for binary release script + #KERNEL_PATH := $(pwd) + #OBJ_PATH := $(pwd) + obj-$(CONFIG_MTK_COMBO) += common/ + obj-$(CONFIG_MTK_COMBO_FM) += drv_fm/ + obj-$(CONFIG_MTK_COMBO_WIFI) += drv_wlan/ + + #Use BT HCI driver + obj-$(CONFIG_MTK_COMBO_BT_HCI) += drv_bt/ + obj-$(CONFIG_MTK_GPS) += gps/ + +# Otherwise we were called directly from the command +# line; invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif diff --git a/drivers/mtk_wcn_combo/Module.symvers b/drivers/mtk_wcn_combo/Module.symvers new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/drivers/mtk_wcn_combo/common/Makefile b/drivers/mtk_wcn_combo/common/Makefile new file mode 100755 index 000000000000..35c5900d1cb2 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/Makefile @@ -0,0 +1,79 @@ +#ccflags-y += -I$(src)/core/include +ccflags-y += -I$(src)/linux/include -I$(src)/core/include -I$(src)/include -I$(src)/ +ccflags-y += -DWMT_PLAT_APEX=1 +ccflags-y += -DWMT_PLAT_ALPS=0 +ccflags-y += -DWMT_UART_RX_MODE_WORK=1 # 1. work thread 0. tasklet +#ifeq ($(MTK_COMBO_CHIP), MT6628) +#EXT_FLAG= +#else +#EXT_FLAG=_mt6628 +#endif +EXT_FLAG= +COMMON_SRC_PATH := $(src) +COMMON_OBJ_PATH := $(src) + +# WMT DRIVER +obj-$(CONFIG_MTK_COMBO_COMM) += mtk_stp_wmt$(EXT_FLAG).o +# WMT DRIVER-core part +mtk_stp_wmt$(EXT_FLAG)-objs := core/wmt_core.o core/wmt_ctrl.o core/wmt_func.o core/wmt_ic_6620.o core/wmt_lib.o core/wmt_conf.o core/wmt_dbg.o core/wmt_exp.o + +#ifeq ($(MTK_COMBO_CHIP), MT6628) +mtk_stp_wmt$(EXT_FLAG)-objs += core/wmt_ic_6628.o +#endif +# WMT DRIVER-linux private part +mtk_stp_wmt$(EXT_FLAG)-objs += linux/wmt_dev.o +mtk_stp_wmt$(EXT_FLAG)-objs += linux/wmt_tm.o + +# WMT DRIVER-OSAL +mtk_stp_wmt$(EXT_FLAG)-objs += linux/osal.o +# WMT DRIVER-platform implementation +#ccflags-y += -D WMT_PLAT_ALPS #Jake modify + +# WMT DRIVER-platform part, specified by string CONFIG_MTK_COMBO_PLAT_PATH +PLAT := $(shell echo $(CONFIG_MTK_COMBO_PLAT_PATH)) + + + +#obj-y += platform/$(PLAT)/mtk_wcn_cmb_stub_$(PLAT).o +mtk_stp_wmt$(EXT_FLAG)-objs += platform/$(PLAT)/wmt_plat_$(PLAT).o +mtk_stp_wmt$(EXT_FLAG)-objs += platform/$(PLAT)/wmt_plat_stub.o + +# FIXME: select desired hw according to project configuration +#ifeq ($(MTK_COMBO_CHIP), MT6628) +#mtk_stp_wmt$(EXT_FLAG)-objs += platform/alps/mtk_wcn_cmb_hw_6628.o +#else +mtk_stp_wmt$(EXT_FLAG)-objs += platform/$(PLAT)/mtk_wcn_cmb_hw.o +#endif + +mtk_stp_wmt$(EXT_FLAG)-objs += core/stp_exp.o core/stp_core.o core/psm_core.o core/btm_core.o linux/stp_dbg.o +#ifeq ($(MTK_COMBO_CHIP), MT6628) +# WMT stub part (built-in kernel image) +obj-y += platform/$(PLAT)/mtk_wcn_cmb_stub_$(PLAT).o +#endif + +obj-$(CONFIG_MTK_COMBO_COMM_UART) += mtk_stp_uart$(EXT_FLAG).o +mtk_stp_uart$(EXT_FLAG)-objs := linux/stp_uart.o + + +obj-$(CONFIG_MTK_COMBO_COMM) += mtk_hif_sdio$(EXT_FLAG).o +mtk_hif_sdio$(EXT_FLAG)-objs := linux/hif_sdio.o +mtk_hif_sdio$(EXT_FLAG)-objs += linux/hif_sdio_chrdev.o +mtk_hif_sdio$(EXT_FLAG)-objs += platform/$(PLAT)/mtk_wcn_cmb_hw.o +mtk_hif_sdio$(EXT_FLAG)-objs += platform/$(PLAT)/wmt_plat_$(PLAT).o +mtk_hif_sdio$(EXT_FLAG)-objs += linux/osal.o + + +# obj-$(CONFIG_MTK_COMBO) += mtk_stp_sdio$(EXT_FLAG).o +# mtk_stp_sdio$(EXT_FLAG)-objs := linux/stp_sdio.o +# mtk_stp_sdio$(EXT_FLAG)-objs += linux/osal.o + + +obj-$(CONFIG_MTK_COMBO_BT) += mtk_stp_bt$(EXT_FLAG).o +mtk_stp_bt$(EXT_FLAG)-objs := linux/stp_chrdev_bt.o + +obj-$(CONFIG_MTK_COMBO_GPS) += mtk_stp_gps$(EXT_FLAG).o +mtk_stp_gps$(EXT_FLAG)-objs := linux/stp_chrdev_gps.o + + +obj-$(CONFIG_MTK_COMBO_WIFI) += mtk_wmt_wifi$(EXT_FLAG).o +mtk_wmt_wifi$(EXT_FLAG)-objs := linux/wmt_chrdev_wifi.o diff --git a/drivers/mtk_wcn_combo/common/core/btm_core.c b/drivers/mtk_wcn_combo/common/core/btm_core.c new file mode 100755 index 000000000000..075abb65a16c --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/btm_core.c @@ -0,0 +1,761 @@ + + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_dbg.h" +#include "stp_core.h" +#include "btm_core.h" + +#define PFX_BTM "[STP-BTM] " +#define STP_BTM_LOG_LOUD 4 +#define STP_BTM_LOG_DBG 3 +#define STP_BTM_LOG_INFO 2 +#define STP_BTM_LOG_WARN 1 +#define STP_BTM_LOG_ERR 0 + +INT32 gBtmDbgLevel = STP_BTM_LOG_INFO; + +#define STP_BTM_LOUD_FUNC(fmt, arg...) if(gBtmDbgLevel >= STP_BTM_LOG_LOUD){ osal_dbg_print(PFX_BTM "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_BTM_DBG_FUNC(fmt, arg...) if(gBtmDbgLevel >= STP_BTM_LOG_DBG){ osal_dbg_print(PFX_BTM "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_BTM_INFO_FUNC(fmt, arg...) if(gBtmDbgLevel >= STP_BTM_LOG_INFO){ osal_dbg_print(PFX_BTM "[I]%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_BTM_WARN_FUNC(fmt, arg...) if(gBtmDbgLevel >= STP_BTM_LOG_WARN){ osal_dbg_print(PFX_BTM "[W]%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_BTM_ERR_FUNC(fmt, arg...) if(gBtmDbgLevel >= STP_BTM_LOG_ERR){ osal_dbg_print(PFX_BTM "[E]%s(%d):ERROR! " fmt, __FUNCTION__ , __LINE__, ##arg);} +#define STP_BTM_TRC_FUNC(f) if(gBtmDbgLevel >= STP_BTM_LOG_DBG){ osal_dbg_print(PFX_BTM "<%s> <%d>\n", __FUNCTION__, __LINE__);} + +INT32 gDumplogflag = 0; +#if WMT_PLAT_ALPS +extern void dump_uart_history(void); +#endif + + +#define ASSERT(expr) + +MTKSTP_BTM_T stp_btm_i; +MTKSTP_BTM_T *stp_btm = &stp_btm_i; + +const PCHAR g_btm_op_name[]={ + "STP_OPID_BTM_RETRY", + "STP_OPID_BTM_RST", + "STP_OPID_BTM_DBG_DUMP", + "STP_OPID_BTM_EXIT" + }; + +#if 0 +static PCHAR _stp_pkt_type(INT32 type){ + + static CHAR s[10]; + + switch(type){ + case WMT_TASK_INDX: + osal_memcpy(s, "WMT", strlen("WMT")+1); + break; + case BT_TASK_INDX: + osal_memcpy(s, "BT", strlen("BT")+1); + break; + case GPS_TASK_INDX: + osal_memcpy(s, "GPS", strlen("GPS")+1); + break; + case FM_TASK_INDX: + osal_memcpy(s, "FM", strlen("FM")+1); + break; + default: + osal_memcpy(s, "UNKOWN", strlen("UNKOWN")+1); + break; + } + + return s; +} +#endif + +static INT32 _stp_btm_put_dump_to_nl(void) +{ + #define NUM_FETCH_ENTRY 8 + + static UINT8 buf[2048]; + static UINT8 tmp[2048]; + + UINT32 buf_len; + STP_PACKET_T *pkt; + STP_DBG_HDR_T *hdr; + INT32 remain=0, index =0; + INT32 retry = 0, rc = 0, nl_retry = 0; + STP_BTM_INFO_FUNC("Enter..\n"); + + index = 0; + tmp[index++]='['; + tmp[index++]='M'; + tmp[index++]=']'; + + do + { + index = 3; + remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); + if (buf_len > 0) + { + pkt = (STP_PACKET_T *)buf; + hdr = &pkt->hdr; + if (hdr->dbg_type == STP_DBG_FW_DMP){ + osal_memcpy(&tmp[index], pkt->raw, pkt->hdr.len); + + if(pkt->hdr.len <= 1500) + { + tmp[index + pkt->hdr.len] = '\n'; + tmp[index + pkt->hdr.len + 1] = '\0'; + + //printk("\n%s\n+++\n", tmp); + rc = stp_dbg_nl_send((PCHAR)&tmp, 2); + + while(rc){ + nl_retry++; + if(nl_retry > 1000){ + break; + } + STP_BTM_WARN_FUNC("**dump send fails, and retry again.**\n"); + osal_msleep(3); + rc = stp_dbg_nl_send((PCHAR)&tmp, 2); + if(!rc){ + STP_BTM_WARN_FUNC("****retry again ok!**\n"); + } + } + //schedule(); + } else { + STP_BTM_INFO_FUNC("dump entry length is over long\n"); + osal_bug_on(0); + } + retry = 0; + } + }else + { + retry ++; + osal_msleep(100); + } + }while((remain > 0) || (retry < 2)); + + STP_BTM_INFO_FUNC("Exit..\n"); + return 0; +} + + +static INT32 _stp_btm_put_dump_to_aee(void) +{ + static UINT8 buf[2048]; + static UINT8 tmp[2048]; + + UINT32 buf_len; + STP_PACKET_T *pkt; + STP_DBG_HDR_T *hdr; + INT32 remain = 0; + INT32 retry = 0; + INT32 ret = 0; + STP_BTM_INFO_FUNC("Enter..\n"); + + do { + remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); + if (buf_len > 0) { + pkt = (STP_PACKET_T*)buf; + hdr = &pkt->hdr; + if (hdr->dbg_type == STP_DBG_FW_DMP) { + osal_memcpy(&tmp[0], pkt->raw, pkt->hdr.len); + + if (pkt->hdr.len <= 1500) { + tmp[pkt->hdr.len] = '\n'; + tmp[pkt->hdr.len + 1] = '\0'; + + ret = stp_dbg_aee_send(tmp, pkt->hdr.len, 0); + } else { + STP_BTM_INFO_FUNC("dump entry length is over long\n"); + osal_bug_on(0); + } + retry = 0; + } + } else { + retry ++; + osal_msleep(100); + } + }while ((remain > 0) || (retry < 2)); + + STP_BTM_INFO_FUNC("Exit..\n"); + return ret; +} + +#define COMBO_DUMP2AEE + +static INT32 _stp_btm_handler(MTKSTP_BTM_T *stp_btm, P_STP_BTM_OP pStpOp) +{ + INT32 ret = -1; + INT32 dump_sink = 1; //core dump target, 0: aee; 1: netlink + + if (NULL == pStpOp) + { + return -1; + } + + switch(pStpOp->opId) + { + case STP_OPID_BTM_EXIT: + // TODO: clean all up? + ret = 0; + break; + + /*tx timeout retry*/ + case STP_OPID_BTM_RETRY: + stp_do_tx_timeout(); + ret = 0; + + break; + + /*whole chip reset*/ + case STP_OPID_BTM_RST: + STP_BTM_INFO_FUNC("whole chip reset start!\n"); + STP_BTM_INFO_FUNC("....+\n"); + if(stp_btm->wmt_notify) + { + stp_btm->wmt_notify(BTM_RST_OP); + ret = 0; + } + else + { + STP_BTM_ERR_FUNC("stp_btm->wmt_notify is NULL."); + ret = -1; + } + + STP_BTM_INFO_FUNC("whole chip reset end!\n"); + + break; + + case STP_OPID_BTM_DBG_DUMP: + /*Notify the wmt to get dump data*/ + STP_BTM_DBG_FUNC("wmt dmp notification\n"); + dump_sink = ((stp_btm->wmt_notify(BTM_GET_AEE_SUPPORT_FLAG) == MTK_WCN_BOOL_TRUE) ? 0 : 1); + + if (dump_sink == 0) { + _stp_btm_put_dump_to_aee(); + } else if (dump_sink == 1) { + _stp_btm_put_dump_to_nl(); + } else { + STP_BTM_ERR_FUNC("unknown sink %d\n", dump_sink); + } + + break; + + + case STP_OPID_BTM_DUMP_TIMEOUT: + // Flush dump data, and reset compressor + STP_BTM_INFO_FUNC("Flush dump data\n"); + wcn_core_dump_flush(0); + break; + + default: + ret = -1; + break; + } + + return ret; +} + +static P_OSAL_OP _stp_btm_get_op ( + MTKSTP_BTM_T *stp_btm, + P_OSAL_OP_Q pOpQ + ) +{ + P_OSAL_OP pOp; + //INT32 ret = 0; + + if (!pOpQ) + { + STP_BTM_WARN_FUNC("!pOpQ \n"); + return NULL; + } + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* acquire lock success */ + RB_GET(pOpQ, pOp); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + + if (!pOp) + { + //STP_BTM_WARN_FUNC("RB_GET fail\n"); + } + + return pOp; +} + +static INT32 _stp_btm_put_op ( + MTKSTP_BTM_T *stp_btm, + P_OSAL_OP_Q pOpQ, + P_OSAL_OP pOp + ) +{ + INT32 ret; + + if (!pOpQ || !pOp) + { + STP_BTM_WARN_FUNC("invalid input param: 0x%p, 0x%p \n", pOpQ, pOp); + return 0;//;MTK_WCN_BOOL_FALSE; + } + + ret = 0; + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + { + RB_PUT(pOpQ, pOp); + } + else + { + ret = -1; + } + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + + if (ret) + { + STP_BTM_WARN_FUNC("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n", pOpQ, RB_COUNT(pOpQ), + &stp_btm->rFreeOpQ, &stp_btm->rActiveOpQ); + return 0; + } + else + { + //STP_BTM_WARN_FUNC("RB_COUNT = %d\n",RB_COUNT(pOpQ)); + return 1; + } +} + +P_OSAL_OP _stp_btm_get_free_op ( + MTKSTP_BTM_T *stp_btm + ) +{ + P_OSAL_OP pOp; + + if (stp_btm) + { + pOp = _stp_btm_get_op(stp_btm, &stp_btm->rFreeOpQ); + if (pOp) + { + osal_memset(&pOp->op, 0, sizeof(pOp->op)); + } + return pOp; + } + else { + return NULL; + } +} + +INT32 _stp_btm_put_act_op ( + MTKSTP_BTM_T *stp_btm, + P_OSAL_OP pOp + ) +{ + INT32 bRet = 0; + INT32 bCleanup = 0; + LONG wait_ret = -1; + + P_OSAL_SIGNAL pSignal = NULL; + + do { + if (!stp_btm || !pOp) + { + break; + } + + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) + { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* put to active Q */ + bRet = _stp_btm_put_op(stp_btm, &stp_btm->rActiveOpQ, pOp); + if(0 == bRet) + { + STP_BTM_WARN_FUNC("put active queue fail\n"); + bCleanup = 1;//MTK_WCN_BOOL_TRUE; + break; + } + + /* wake up wmtd */ + osal_trigger_event(&stp_btm->STPd_event); + + if (pSignal->timeoutValue == 0) + { + bRet = 1;//MTK_WCN_BOOL_TRUE; + /* clean it in wmtd */ + break; + } + + /* wait result, clean it here */ + bCleanup = 1;//MTK_WCN_BOOL_TRUE; + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal); + + STP_BTM_DBG_FUNC("wait completion:%ld\n", wait_ret); + if (!wait_ret) + { + STP_BTM_ERR_FUNC("wait completion timeout \n"); + // TODO: how to handle it? retry? + } + else + { + if (pOp->result) + { + STP_BTM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); + } + + bRet = (pOp->result) ? 0 : 1; + } + } while(0); + + if (bCleanup) { + /* put Op back to freeQ */ + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } + + return bRet; +} + +static INT32 _stp_btm_wait_for_msg(void *pvData) +{ + MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *)pvData; + return ((!RB_EMPTY(&stp_btm->rActiveOpQ)) || osal_thread_should_stop(&stp_btm->BTMd)); +} + +static INT32 _stp_btm_proc (void *pvData) +{ + MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *)pvData; + P_OSAL_OP pOp; + INT32 id; + INT32 result; + + if (!stp_btm) + { + STP_BTM_WARN_FUNC("!stp_btm \n"); + return -1; + } + + for (;;) + { + pOp = NULL; + + osal_wait_for_event(&stp_btm->STPd_event, + _stp_btm_wait_for_msg, + (void *)stp_btm + ); + + if (osal_thread_should_stop(&stp_btm->BTMd)) + { + STP_BTM_INFO_FUNC("should stop now... \n"); + // TODO: clean up active opQ + break; + } + +#if 1 + if(gDumplogflag) + { + //printk("enter place1\n"); + #if WMT_PLAT_ALPS + dump_uart_history(); + #endif + gDumplogflag = 0; + continue; + } +#endif + + /* get Op from activeQ */ + pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ); + + if (!pOp) + { + STP_BTM_WARN_FUNC("get_lxop activeQ fail\n"); + continue; + } + + id = osal_op_get_id(pOp); + + STP_BTM_DBG_FUNC("======> lxop_get_opid = %d, %s, remaining count = *%d*\n", + id, (id >= 4)?("???"):(g_btm_op_name[id]), RB_COUNT(&stp_btm->rActiveOpQ)); + + if (id >= STP_OPID_BTM_NUM) + { + STP_BTM_WARN_FUNC("abnormal opid id: 0x%x \n", id); + result = -1; + goto handler_done; + } + + result = _stp_btm_handler(stp_btm, &pOp->op); + +handler_done: + + if (result) + { + STP_BTM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, (id >= 4)?("???"):(g_btm_op_name[id]), result); + } + + if (osal_op_is_wait_for_signal(pOp)) + { + osal_op_raise_signal(pOp, result); + } + else + { + /* put Op back to freeQ */ + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } + + if (STP_OPID_BTM_EXIT == id) + { + break; + } else if (STP_OPID_BTM_RST == id) { + /* prevent multi reset case */ + stp_btm_reset_btm_wq(stp_btm); + } + } + + STP_BTM_INFO_FUNC("exits \n"); + + return 0; +}; + +static inline INT32 _stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_btm == NULL) + { + return STP_BTM_OPERATION_FAIL; + } + else + { + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) + { + STP_BTM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + pOp->op.opId = STP_OPID_BTM_RST; + pOp->signal.timeoutValue= 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + } + return retval; +} + +static inline INT32 _stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm){ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_btm == NULL) + { + return STP_BTM_OPERATION_FAIL; + } + else + { + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) + { + STP_BTM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + pOp->op.opId = STP_OPID_BTM_RETRY; + pOp->signal.timeoutValue= 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + } + return retval; +} + + +static inline INT32 _stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm){ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (!stp_btm) { + return STP_BTM_OPERATION_FAIL; + } else { + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + pOp->op.opId = STP_OPID_BTM_DUMP_TIMEOUT; + pOp->signal.timeoutValue= 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + } + return retval; +} + + +static inline INT32 _stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm){ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_btm == NULL) + { + return STP_BTM_OPERATION_FAIL; + } + else + { + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) + { + //STP_BTM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + pOp->op.opId = STP_OPID_BTM_DBG_DUMP; + pOp->signal.timeoutValue= 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + } + return retval; +} + +INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_rst_wq(stp_btm); +} + +INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_stp_retry_wq(stp_btm); +} + +INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_coredump_timeout_wq(stp_btm); +} + +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_dmp_wq(stp_btm); +} + +MTKSTP_BTM_T *stp_btm_init(void) +{ + INT32 i = 0x0; + INT32 ret =-1; + + osal_unsleepable_lock_init(&stp_btm->wq_spinlock); + osal_event_init(&stp_btm->STPd_event); + stp_btm->wmt_notify = wmt_lib_btm_cb; + + RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); + RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); + + /* Put all to free Q */ + for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) + { + osal_signal_init(&(stp_btm->arQue[i].signal)); + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); + } + + /*Generate PSM thread, to servie STP-CORE for packet retrying and core dump receiving*/ + stp_btm->BTMd.pThreadData = (VOID *)stp_btm; + stp_btm->BTMd.pThreadFunc = (VOID *)_stp_btm_proc; + osal_memcpy(stp_btm->BTMd.threadName, BTM_THREAD_NAME , osal_strlen(BTM_THREAD_NAME)); + + ret = osal_thread_create(&stp_btm->BTMd); + if (ret < 0) + { + STP_BTM_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT1; + } + + /* Start STPd thread*/ + ret = osal_thread_run(&stp_btm->BTMd); + if(ret < 0) + { + STP_BTM_ERR_FUNC("osal_thread_run FAILS\n"); + goto ERR_EXIT1; + } + + return stp_btm; + +ERR_EXIT1: + + return NULL; + +} + +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm){ + + UINT32 ret = -1; + + STP_BTM_INFO_FUNC("btm deinit\n"); + + if(!stp_btm) + { + return STP_BTM_OPERATION_FAIL; + } + + ret = osal_thread_destroy(&stp_btm->BTMd); + if(ret < 0) + { + STP_BTM_ERR_FUNC("osal_thread_destroy FAILS\n"); + return STP_BTM_OPERATION_FAIL; + } + + return STP_BTM_OPERATION_SUCCESS; +} + + +INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm) +{ + UINT32 i = 0; + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); + RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* Put all to free Q */ + for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) + { + osal_signal_init(&(stp_btm->arQue[i].signal)); + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); + } + + return 0; +} + + +INT32 stp_notify_btm_dump(MTKSTP_BTM_T *stp_btm) +{ + //printk("%s:enter++\n",__func__); + if(NULL == stp_btm) + { + osal_dbg_print("%s: NULL POINTER\n",__func__); + return -1; + } + else + { + gDumplogflag = 1; + osal_trigger_event(&stp_btm->STPd_event); + return 0; + } +} + diff --git a/drivers/mtk_wcn_combo/common/core/dbg_core.c b/drivers/mtk_wcn_combo/common/core/dbg_core.c new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/drivers/mtk_wcn_combo/common/core/include/btm_core.h b/drivers/mtk_wcn_combo/common/core/include/btm_core.h new file mode 100755 index 000000000000..3907f95bd1c9 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/btm_core.h @@ -0,0 +1,107 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _BTM_CORE_H +#define _BTM_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_wmt.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define STP_BTM_OPERATION_FAIL (-1) +#define STP_BTM_OPERATION_SUCCESS (0) + +#define STP_BTM_OP_BUF_SIZE (64) + +#define BTM_THREAD_NAME "mtk_stp_btm" +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_STP_BTM_OPID_T { + STP_OPID_BTM_RETRY = 0x0, + STP_OPID_BTM_RST = 0x1, + STP_OPID_BTM_DBG_DUMP = 0x2, + STP_OPID_BTM_DUMP_TIMEOUT = 0x3, + STP_OPID_BTM_EXIT, + STP_OPID_BTM_NUM +} ENUM_STP_BTM_OPID_T, *P_ENUM_STP_BTM_OPID_T; + +typedef OSAL_OP_DAT STP_BTM_OP; +typedef P_OSAL_OP_DAT P_STP_BTM_OP; + +typedef struct mtk_stp_btm +{ + OSAL_THREAD BTMd; /* main thread (wmtd) handle */ + OSAL_EVENT STPd_event; + OSAL_UNSLEEPABLE_LOCK wq_spinlock; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[STP_BTM_OP_BUF_SIZE]; /* real op instances */ + + /*wmt_notify*/ + INT32 (*wmt_notify)(MTKSTP_BTM_WMT_OP_T); +}MTKSTP_BTM_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_dump(MTKSTP_BTM_T *stp_btm); + + + +MTKSTP_BTM_T *stp_btm_init(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/mtk_wcn_combo/common/core/include/dbg_core.h b/drivers/mtk_wcn_combo/common/core/include/dbg_core.h new file mode 100755 index 000000000000..c2444f35fdf1 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/dbg_core.h @@ -0,0 +1,63 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +#ifndef _DBG_CORE_H +#define _DBG_CORE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/mtk_wcn_combo/common/core/include/psm_core.h b/drivers/mtk_wcn_combo/common/core/include/psm_core.h new file mode 100755 index 000000000000..7c95bb096e34 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/psm_core.h @@ -0,0 +1,209 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +#ifndef _PSM_CORE_H +#define _PSM_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_wmt.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define PFX_PSM "[STP-PSM] " +#define STP_PSM_LOG_LOUD 4 +#define STP_PSM_LOG_DBG 3 +#define STP_PSM_LOG_INFO 2 +#define STP_PSM_LOG_WARN 1 +#define STP_PSM_LOG_ERR 0 + +#define ASSERT(expr) +#define STP_PSM_FIFO_SIZE 0x2000//8kbytes +#define STP_PSM_TX_SIZE 0x800 //2kbytes + +#define STP_PSM_OPERATION_FAIL (-1) +#define STP_PSM_OPERATION_SUCCESS (0) + +#define STP_PSM_PACKET_SIZE_MAX (2000) +#if WMT_UART_RX_MODE_WORK +#define CFG_PSM_CORE_FIFO_SPIN_LOCK 0 +#else +#define CFG_PSM_CORE_FIFO_SPIN_LOCK 1 +#endif + + +#define PSM_HANDLING 127 + +#define STP_PSM_WMT_PS_TASK_HANDLING_TIME 30 //20 milli-seconds +#define STP_PSM_IDLE_TIME_SLEEP 5000 //temporary for stress testing +#define STP_PSM_SDIO_IDLE_TIME_SLEEP 100 //temporary for SDIO stress testing +#define STP_PSM_WAIT_EVENT_TIMEOUT 6000 + +#define STP_PSM_WMT_EVENT_SLEEP_EN (0x1UL << 0) +#define STP_PSM_WMT_EVENT_WAKEUP_EN (0x1UL << 1) +#define STP_PSM_BLOCK_DATA_EN (0x1UL << 2) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (0x1UL << 3) +#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (0x1UL << 4) +#define STP_PSM_RESET_EN (0x1UL << 5) +#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (0x1UL << 6) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (0x1UL << 7) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (0x1UL << 8) + + +/* OP command ring buffer : must be power of 2 */ +#define STP_OP_BUF_SIZE (16) + +#define PSM_THREAD_NAME "mtk_stp_psm" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum { + ACT = 0, + ACT_INACT, + INACT, + INACT_ACT, + STP_PSM_MAX_STATE, +}MTKSTP_PSM_STATE_T; + +typedef enum _ENUM_STP_OPID_T { + STP_OPID_PSM_SLEEP = 0, + STP_OPID_PSM_WAKEUP, + STP_OPID_PSM_HOST_AWAKE, + STP_OPID_PSM_EXIT, + STP_OPID_PSM_NUM, + STP_OPID_PSM_INALID = STP_OPID_PSM_NUM, +} ENUM_STP_OPID_T, *P_ENUM_STP_OPID_T; + +typedef enum { + MON=0, + UNMON, +}MTKSTP_PSM_MONSTATE_T; + +typedef INT32 (*wmt_notify_t)(MTKSTP_PSM_ACTION_T action); +typedef INT32 (*stp_tx_cb_t)(unsigned char*buffer, UINT32 length, UINT8 type); + +typedef OSAL_OP_DAT STP_OP; +typedef P_OSAL_OP_DAT P_STP_OP; +#if CFG_PSM_CORE_FIFO_SPIN_LOCK +typedef OSAL_UNSLEEPABLE_LOCK PSM_FIFO_LOCK, *PPSM_FIFO_LOCK; +#else +typedef OSAL_SLEEPABLE_LOCK PSM_FIFO_LOCK, *PPSM_FIFO_LOCK; +#endif + +typedef struct mtk_stp_psm +{ + OSAL_THREAD PSMd; /* main thread (wmtd) handle */ + OSAL_EVENT STPd_event; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[STP_OP_BUF_SIZE]; /* real op instances */ + + //OSAL_OP current_active_op; + //P_OSAL_OP current_active_op; + UINT32 last_active_opId; + MTKSTP_PSM_STATE_T work_state; /*working state*/ + INT32 flag; + + /* in normal cases, sleep op is always enabled; but in error cases, we can't execute sleep cmd, Eg: FW assert, core dump*/ + INT32 sleep_en; + +// OSAL_UNSLEEPABLE_LOCK flagSpinlock; + INT32 idle_time_to_sleep; + OSAL_WAKE_LOCK wake_lock; + OSAL_TIMER psm_timer; /*monitor if active*/ + OSAL_EVENT wait_wmt_q; + OSAL_FIFO hold_fifo; + + PSM_FIFO_LOCK hold_fifo_lock; + + OSAL_UNSLEEPABLE_LOCK wq_spinlock; + OSAL_SLEEPABLE_LOCK user_lock; + OSAL_SLEEPABLE_LOCK stp_psm_lock; + INT32 (*wmt_notify)(MTKSTP_PSM_ACTION_T action); + INT32 (*stp_tx_cb)(unsigned char*buffer,UINT32 length, UINT8 type); + MTK_WCN_BOOL (*is_wmt_quick_ps_support)(VOID); + UINT8 out_buf[STP_PSM_TX_SIZE]; +}MTKSTP_PSM_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*stp-psm external function*/ +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm); + +INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T * stp_psm); +INT32 stp_psm_is_disable(MTKSTP_PSM_T * stp_psm); +INT32 stp_psm_has_pending_data(MTKSTP_PSM_T * stp_psm); +INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_hold_data ( + MTKSTP_PSM_T *stp_psm, + const UINT8 *buffer, + const UINT32 len, + const UINT8 type + ); +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir); +INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep); +struct mtk_stp_psm *stp_psm_init(void); +INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm); +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel); +INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state); +MTK_WCN_BOOL stp_psm_is_quick_ps_support (VOID); + +INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/mtk_wcn_combo/common/core/include/stp_core.h b/drivers/mtk_wcn_combo/common/core/include/stp_core.h new file mode 100755 index 000000000000..5c5668527316 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/stp_core.h @@ -0,0 +1,555 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _STP_CORE_H +#define _STP_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_exp.h" +#include "psm_core.h" +#include "btm_core.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONFIG_POWER_SAVING_SUPPORT +#if WMT_UART_RX_MODE_WORK +#define CFG_STP_CORE_CTX_SPIN_LOCK 0 +#else +#define CFG_STP_CORE_CTX_SPIN_LOCK 1 +#endif + + + +#define PFX "[STP] " +#define STP_LOG_DBG 4 +#define STP_LOG_PKHEAD 3 +#define STP_LOG_INFO 2 +#define STP_LOG_WARN 1 +#define STP_LOG_ERR 0 + +extern unsigned int gStpDbgLvl; + +#define STP_DBG_FUNC(fmt, arg...) if(gStpDbgLvl >= STP_LOG_DBG){ osal_dbg_print(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_INFO_FUNC(fmt, arg...) if(gStpDbgLvl >= STP_LOG_INFO){ osal_dbg_print(PFX "%s:[I] " fmt, __FUNCTION__ ,##arg);} +#define STP_WARN_FUNC(fmt, arg...) if(gStpDbgLvl >= STP_LOG_WARN){ osal_dbg_print(PFX "%s:[W] " fmt, __FUNCTION__ ,##arg);} +#define STP_ERR_FUNC(fmt, arg...) if(gStpDbgLvl >= STP_LOG_ERR){ osal_dbg_print(PFX "%s:[E] " fmt, __FUNCTION__ ,##arg);} +#define STP_TRC_FUNC(f) if(gStpDbgLvl >= STP_LOG_DBG){ osal_dbg_print(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);} + +#define STP_DUMP_PACKET_HEAD(a, b, c) if(gStpDbgLvl >= STP_LOG_PKHEAD){stp_dump_data(a, b, c);} +#define STP_TRACE_FUNC(fmt, arg...) if(gStpDbgLvl >= STP_LOG_DBG){ osal_dbg_print(PFX "%s: " fmt, __FUNCTION__ ,##arg);} + +#define MTKSTP_UART_FULL_MODE 0x01 +#define MTKSTP_UART_MAND_MODE 0x02 +#define MTKSTP_SDIO_MODE 0x04 + +#define MTKSTP_BUFFER_SIZE (16384) + +/*To check function driver's status by the the interface*/ +/*Operation definition*/ +#define OP_FUNCTION_ACTIVE 0 + +/*Driver's status*/ +#define STATUS_OP_INVALID 0 +#define STATUS_FUNCTION_INVALID 1 + +#define STATUS_FUNCTION_ACTIVE 31 +#define STATUS_FUNCTION_INACTIVE 32 + +#define MTKSTP_CRC_SIZE (2) +#define MTKSTP_HEADER_SIZE (4) +#define MTKSTP_SEQ_SIZE (8) + +/*#define MTKSTP_WINSIZE (4)*/ +#define MTKSTP_WINSIZE (7) +#define MTKSTP_TX_TIMEOUT (180) /*TODO: Baudrate to decide this*/ +#define MTKSTP_RETRY_LIMIT (10) + +#define INDEX_INC(idx) \ +{ \ + idx++; \ + idx &= 0x7; \ +} + +#define INDEX_DEC(idx) \ +{ \ + idx--; \ + idx &= 0x7; \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef INT32 (*IF_TX)(const UINT8 *data, const UINT32 size, UINT32 *written_size); +/* event/signal */ +typedef INT32 (*EVENT_SET)(UINT8 function_type); +typedef INT32 (*EVENT_TX_RESUME)(UINT8 winspace); +typedef INT32 (*FUNCTION_STATUS)(UINT8 type, UINT8 op); +typedef INT32 (*WMT_NOTIFY_FUNC_T)(UINT32 action); +typedef INT32 (*BTM_NOTIFY_WMT_FUNC_T)(INT32); + + +typedef struct +{ + /* common interface */ + IF_TX cb_if_tx; + /* event/signal */ + EVENT_SET cb_event_set; + EVENT_TX_RESUME cb_event_tx_resume; + FUNCTION_STATUS cb_check_funciton_status; +}mtkstp_callback; + +typedef enum +{ + MTKSTP_SYNC = 0, + MTKSTP_SEQ, + MTKSTP_ACK, + MTKSTP_NAK, + MTKSTP_TYPE, + MTKSTP_LENGTH, + MTKSTP_CHECKSUM, + MTKSTP_DATA, + MTKSTP_CRC1, + MTKSTP_CRC2, + MTKSTP_RESYNC1, + MTKSTP_RESYNC2, + MTKSTP_RESYNC3, + MTKSTP_RESYNC4, + MTKSTP_FW_MSG, +} mtkstp_parser_state; + +typedef struct +{ + mtkstp_parser_state state; + UINT8 seq; + UINT8 ack; + UINT8 nak; + UINT8 type; + UINT16 length; + UINT8 checksum; + UINT16 crc; +} mtkstp_parser_context_struct; + +typedef struct +{ + UINT8 txseq; // last tx pkt's seq + 1 + UINT8 txack; // last tx pkt's ack + UINT8 rxack; // last rx pkt's ack + UINT8 winspace; // current sliding window size + UINT8 expected_rxseq; // last rx pkt's seq + 1 + UINT8 retry_times; +} mtkstp_sequence_context_struct; + +typedef struct +{ + //MTK_WCN_MUTEX mtx; + OSAL_UNSLEEPABLE_LOCK mtx; + UINT8 buffer[MTKSTP_BUFFER_SIZE]; + UINT32 read_p; + UINT32 write_p; +} mtkstp_ring_buffer_struct; + +typedef struct +{ + UINT8 inband_rst_set; + UINT32 rx_counter; // size of current processing pkt in rx_buf[] + UINT8 rx_buf[MTKSTP_BUFFER_SIZE]; // input buffer of STP, room for current processing pkt + UINT32 tx_read; // read ptr of tx_buf[] + UINT32 tx_write; // write ptr of tx_buf[] + UINT8 tx_buf[MTKSTP_BUFFER_SIZE]; // output buffer of STP + UINT32 tx_start_addr[MTKSTP_SEQ_SIZE]; // ptr of each pkt in tx_buf[] + UINT32 tx_length[MTKSTP_SEQ_SIZE]; // length of each pkt in tx_buf[] + mtkstp_ring_buffer_struct ring[MTKSTP_MAX_TASK_NUM]; // ring buffers for each function driver + mtkstp_parser_context_struct parser; // current rx pkt's content + mtkstp_sequence_context_struct sequence; // state machine's current status + //MTK_WCN_MUTEX stp_mutex; + #if CFG_STP_CORE_CTX_SPIN_LOCK + OSAL_UNSLEEPABLE_LOCK stp_mutex; + #else + OSAL_SLEEPABLE_LOCK stp_mutex; + #endif + //MTK_WCN_TIMER tx_timer; // timer for tx timeout handling + OSAL_TIMER tx_timer; + + MTKSTP_PSM_T *psm; + MTKSTP_BTM_T *btm; + UINT8 f_enable; /* default disabled */ + UINT8 f_ready; /* default non-ready */ + UINT8 f_pending_type; + UINT8 f_coredump; /*block tx flag, for now, only when f/w assert happens, we will set this bit on*/ + UINT8 en_coredump; + /* Flag to identify Blueztooth is Bluez/or MTK Stack*/ + MTK_WCN_BOOL f_bluez; + MTK_WCN_BOOL f_dbg_en; + MTK_WCN_BOOL f_autorst_en; + + + + /* Flag to identify STP by SDIO or UART */ + UINT32 f_mode; + + /* Flag to indicate the last WMT CLOSE*/ + UINT32 f_wmt_last_close; +}mtkstp_context_struct; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_init +* DESCRIPTION +* init STP kernel +* PARAMETERS +* cb_func [IN] function pointers of system APIs +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_deinit +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 mtk_wcn_stp_deinit(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_enable +* DESCRIPTION +* enable/disable STP +* PARAMETERS +* value [IN] 0 = disable, others = enable +* RETURNS +* INT32 0 = success, others = error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_enable(INT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/non-ready STP +* PARAMETERS +* value [IN] 0 = non-ready, others = ready +* RETURNS +* INT32 0 = success, others = error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_ready(INT32 value); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get f/w assert flag in STP context +* PARAMETERS +* VOID +* RETURNS +* INT32 0= f/w assert flag is not set, others=f/w assert flag is set +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_get(VOID); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 length transmitted +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data_raw(const UINT8 *buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_mode(UINT32 sdio_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART Fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Fullset, FALSE:UART Fullset +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART Mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Mandatory, FALSE:UART Mandatory +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_sdio_mode +* DESCRIPTION +* Is stp use SDIO mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void); + + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To sync to oringnal stp state with f/w stp +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_inband_reset(void); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To send testing command to chip +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_test_cmd(INT32 no); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To control STP debugging mechanism +* PARAMETERS +* func_no: function control, func_op: dumpping filer, func_param: dumpping parameter +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_debug_ctrl(INT32 func_no, INT32 func_op, INT32 func_param); +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush +* DESCRIPTION +* flush all stp context +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_flush_context(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_rx_queue +* DESCRIPTION +* flush all stp rx queue +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_flush_rx_queue(UINT32 type); + +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode); + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst); + +/*stp_psm support*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_notify_stp +* DESCRIPTION +* WMT notification to STP that power saving job is done or not +* PARAMETERS +* +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_notify_stp(const UINT32 action); + +extern int mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_enabla +* DESCRIPTION +* enable STP PSM +* PARAMETERS +* int idle_time_to_sleep: IDLE time to sleep +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_enable(int idle_time_to_sleep); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP PSM +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_disable(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_reset +* DESCRIPTION +* reset STP PSM (used on whole chip reset) +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_reset(void); +extern void stp_do_tx_timeout(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_btm_get_dmp +* DESCRIPTION +* get stp dump related information +* PARAMETERS +* buffer: dump placement, len: dump size +* RETURNS +* 0: Success Negative Value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_btm_get_dmp(char *buf, int *len); + +extern int mtk_wcn_stp_dbg_enable(void); + +extern int mtk_wcn_stp_dbg_disable(void); + +extern void mtk_wcn_stp_set_if_tx_type (ENUM_STP_TX_IF_TYPE stp_if_type); + +extern int mtk_wcn_sys_if_rx(UINT8 *data, INT32 size); + +extern MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel); + +extern INT32 mtk_wcn_stp_dbg_dump_package(VOID); + +extern int stp_drv_init(void); + +extern void stp_drv_exit(void); + +extern INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on); + +extern INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on); + +extern INT32 mtk_wcn_stp_coredump_flag_get(VOID); +extern INT32 mtk_wcn_stp_notify_sleep_for_thermal(void); + + +extern INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_CORE_H_ */ diff --git a/drivers/mtk_wcn_combo/common/core/include/stp_wmt.h b/drivers/mtk_wcn_combo/common/core/include/stp_wmt.h new file mode 100755 index 000000000000..59cf91a6fc68 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/stp_wmt.h @@ -0,0 +1,89 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _STP_WMT_H +#define _STP_WMT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum { + BTM_RST_OP = 0, + BTM_DMP_OP = 1, + BTM_GET_AEE_SUPPORT_FLAG= 2, + BTM_MAX_OP, +}MTKSTP_BTM_WMT_OP_T; + +typedef enum { + SLEEP = 0, + HOST_AWAKE, + WAKEUP, + EIRQ, + ROLL_BACK, + STP_PSM_MAX_ACTION +}MTKSTP_PSM_ACTION_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +extern MTK_WCN_BOOL wmt_lib_btm_cb ( + MTKSTP_BTM_WMT_OP_T op + ); + +extern INT32 wmt_lib_ps_stp_cb ( + MTKSTP_PSM_ACTION_T action + ); +extern MTK_WCN_BOOL wmt_lib_is_quick_ps_support (VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_WMT_H_*/ + + + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_conf.h b/drivers/mtk_wcn_combo/common/core/include/wmt_conf.h new file mode 100755 index 000000000000..2b2197f66543 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_conf.h @@ -0,0 +1,81 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_CONF_H_ +#define _WMT_CONF_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CUST_CFG_WMT "WMT.cfg" +#define CUST_CFG_WMT_PREFIX "/system/etc/firmware/" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_conf_read_file(VOID); +P_WMT_GEN_CONF wmt_conf_get_cfg(VOID); +INT32 wmt_conf_set_cfg_file(const char *name); + + +#endif /* _WMT_CONF_H_ */ + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_core.h b/drivers/mtk_wcn_combo/common/core/include/wmt_core.h new file mode 100755 index 000000000000..c130afec1a55 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_core.h @@ -0,0 +1,460 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_CORE_H_ +#define _WMT_CORE_H_ + +#include "osal.h" +#include "wmt_ctrl.h" +#include "wmt_exp.h" +#include "wmt_plat.h" +//TODO: [GeorgeKuo][FixMe] remove temporarily +//#include "mtk_wcn_cmb_stub.h" /* for AIF state definition */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#if defined(MT6620E3) || defined(MT6620E6) //need modify this part +#define CFG_CORE_MT6620_SUPPORT 1 /* whether MT6620 is supported or not */ +#else +#define CFG_CORE_MT6620_SUPPORT 1 /* whether MT6620 is supported or not */ +#endif + +#if defined(MT6628) +#define CFG_CORE_MT6628_SUPPORT 1 /* whether MT6628 is supported or not */ +#else +#define CFG_CORE_MT6628_SUPPORT 1 /* whether MT6628 is supported or not */ +#endif + +// TODO:[ChangeFeature][George] move this definition outside so that wmt_dev can remove wmt_core.h inclusion. +#define defaultPatchName "mt66xx_patch_hdr.bin" + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define BCNT_PATCH_BUF_HEADROOM (8) + +#define DWCNT_HIF_CONF (4) +#define DWCNT_STRAP_CONF (4) +#define DWCNT_RESERVED (8) +#define DWCNT_CTRL_DATA (16) + + +#if 0 // TODO: [obsolete][GeorgeKuo]: remove ubsolete definitions +#define WMT_SET (1) +#define WMT_QUERY (0) +#define WMT_PKT_FMT_RAW (1) +#define WMT_PKT_FMT_STP (0) +#endif + +#define WMT_FUNC_CTRL_ON (MTK_WCN_BOOL_TRUE) +#define WMT_FUNC_CTRL_OFF (MTK_WCN_BOOL_FALSE) + +#define WMT_HDR_LEN (4) /* header length */ +#define WMT_STS_LEN (1) /* status length */ +#define WMT_FLAG_LEN (1) +#define WMT_HIF_UART_INFO_LEN (4) +#define WMT_FUNC_CTRL_PARAM_LEN (1) +#define WMT_LPBK_CMD_LEN (5) +#define WMT_LPBK_BUF_LEN (1024+WMT_LPBK_CMD_LEN) +#define WMT_DEFAULT_BAUD_RATE (115200) + +#define INIT_CMD(c, e, s) {.cmd= c, .cmdSz=sizeof(c), .evt=e, .evtSz=sizeof(e), .str=s} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_WMT_FM_T +{ + WMT_FM_INVALID = 0, + WMT_FM_I2C = 1, + WMT_FM_COMM = 2, + WMT_FM_MAX +} ENUM_WMT_FM_T, *P_ENUM_WMT_FM_T; + +typedef enum _ENUM_WMT_HIF_T +{ + WMT_HIF_UART = 0, + WMT_HIF_SDIO = 1, + WMT_HIF_MAX +} ENUM_WMT_HIF_T, *P_ENUM_WMT_HIF_T; + +#if 0 /* [George] moved to wmt_exp.h for hif_sdio's use */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1*/ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +typedef enum _ENUM_WMT_OPID_T { + WMT_OPID_HIF_CONF = 0, + WMT_OPID_PWR_ON = 1, + WMT_OPID_PWR_OFF = 2, + WMT_OPID_FUNC_ON = 3, + WMT_OPID_FUNC_OFF = 4, + WMT_OPID_REG_RW = 5, // TODO:[ChangeFeature][George] is this OP obsoleted? + WMT_OPID_EXIT = 6, + WMT_OPID_PWR_SV = 7, + WMT_OPID_DSNS = 8, + WMT_OPID_LPBK = 9, + WMT_OPID_CMD_TEST = 10, + WMT_OPID_HW_RST = 11, + WMT_OPID_SW_RST = 12, + WMT_OPID_BAUD_RST = 13, + WMT_OPID_STP_RST = 14, + WMT_OPID_THERM_CTRL = 15, + WMT_OPID_EFUSE_RW = 16, + WMT_OPID_GPIO_CTRL = 17, + WMT_OPID_SDIO_CTRL = 18, + WMT_OPID_FW_COREDMP = 19, + WMT_OPID_GPIO_STATE = 20, + WMT_OPID_MAX +} ENUM_WMT_OPID_T, *P_ENUM_WMT_OPID_T; + +typedef OSAL_OP_DAT WMT_OP; +typedef P_OSAL_OP_DAT P_WMT_OP; + +typedef enum _ENUM_WMT_UART_FC_T +{ + WMT_UART_NO_FC = 0, + WMT_UART_MTK_SW_FC = 1, + WMT_UART_LUX_SW_FC = 2, + WMT_UART_HW_FC = 3, + WMT_UART_MAX +} ENUM_WMT_UART_FC_T, *P_ENUM_UART_FC_T; + + +typedef struct _WMT_HIF_CONF { + UINT32 hifType; // HIF Type + UINT32 uartFcCtrl; // UART FC config + UINT32 au4HifConf[DWCNT_HIF_CONF]; // HIF Config + UINT32 au4StrapConf[DWCNT_STRAP_CONF]; // Strap Config +} WMT_HIF_CONF, *P_WMT_HIF_CONF; + +typedef INT32 (*WMT_OPID_FUNC)(P_WMT_OP); + +typedef struct _WMT_GEN_CONF { + UCHAR cfgExist; + + UCHAR coex_wmt_ant_mode; + UCHAR coex_wmt_wifi_time_ctl; + UCHAR coex_wmt_ext_pta_dev_on; + + UCHAR coex_bt_rssi_upper_limit; + UCHAR coex_bt_rssi_mid_limit; + UCHAR coex_bt_rssi_lower_limit; + UCHAR coex_bt_pwr_high; + UCHAR coex_bt_pwr_mid; + UCHAR coex_bt_pwr_low; + + UCHAR coex_wifi_rssi_upper_limit; + UCHAR coex_wifi_rssi_mid_limit; + UCHAR coex_wifi_rssi_lower_limit; + UCHAR coex_wifi_pwr_high; + UCHAR coex_wifi_pwr_mid; + UCHAR coex_wifi_pwr_low; + + UCHAR coex_ext_pta_hi_tx_tag; + UCHAR coex_ext_pta_hi_rx_tag; + UCHAR coex_ext_pta_lo_tx_tag; + UCHAR coex_ext_pta_lo_rx_tag; + UINT16 coex_ext_pta_sample_t1; + UINT16 coex_ext_pta_sample_t2; + UCHAR coex_ext_pta_wifi_bt_con_trx; + + UINT32 coex_misc_ext_pta_on; + UINT32 coex_misc_ext_feature_set; + /*GPS LNA setting*/ + UCHAR wmt_gps_lna_pin; + UCHAR wmt_gps_lna_enable; + /*Power on sequence*/ + UCHAR pwr_on_rtc_slot; + UCHAR pwr_on_ldo_slot; + UCHAR pwr_on_rst_slot; + UCHAR pwr_on_off_slot; + UCHAR pwr_on_on_slot; + UCHAR co_clock_flag; + + /* Combo chip side SDIO driving setting */ + UINT32 sdio_driving_cfg; + +} WMT_GEN_CONF, *P_WMT_GEN_CONF; + +typedef enum _ENUM_DRV_STS_ { +#if 0 + DRV_STS_INVALID = 0, + DRV_STS_UNREG = 1, /* Initial State */ +#endif + DRV_STS_POWER_OFF = 0, /* initial state */ + DRV_STS_POWER_ON = 1, /* powered on, only WMT */ + DRV_STS_FUNC_ON = 2, /* FUNC ON */ + DRV_STS_MAX +} ENUM_DRV_STS, *P_ENUM_DRV_STS; + +typedef enum _WMT_IC_PIN_ID_ +{ + WMT_IC_PIN_AUDIO = 0, + WMT_IC_PIN_EEDI = 1, + WMT_IC_PIN_EEDO = 2, + WMT_IC_PIN_GSYNC = 3, + WMT_IC_PIN_MAX +}WMT_IC_PIN_ID, *P_WMT_IC_PIN_ID; + + +typedef enum _WMT_IC_PIN_STATE_ +{ + WMT_IC_PIN_EN = 0, + WMT_IC_PIN_DIS = 1, + WMT_IC_AIF_0 = 2, // = CMB_STUB_AIF_0, + WMT_IC_AIF_1 = 3, // = CMB_STUB_AIF_1, + WMT_IC_AIF_2 = 4, // = CMB_STUB_AIF_2, + WMT_IC_AIF_3 = 5, // = CMB_STUB_AIF_3, + WMT_IC_PIN_MUX = 6, + WMT_IC_PIN_GPIO = 7, + WMT_IC_PIN_GPIO_HIGH = 8, + WMT_IC_PIN_GPIO_LOW = 8, + WMT_IC_PIN_STATE_MAX +} WMT_IC_PIN_STATE, *P_WMT_IC_PIN_STATE; + +typedef enum _WMT_CO_CLOCK_ +{ + WMT_CO_CLOCK_DIS = 0, + WMT_CO_CLOCK_EN = 1, + WMT_CO_CLOCK_MAX +} WMT_CO_CLOCK, *P_WMT_CO_CLOCK; + + +typedef INT32 (*SW_INIT)(P_WMT_HIF_CONF pWmtHifConf); +typedef INT32 (*SW_DEINIT)(P_WMT_HIF_CONF pWmtHifConf); +typedef INT32 (*IC_PIN_CTRL)(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); +typedef INT32 (*IC_VER_CHECK)(VOID); +typedef INT32 (*CO_CLOCK_CTRL)(WMT_CO_CLOCK on); +typedef MTK_WCN_BOOL(*IS_QUICK_SLEEP_SUPPORT)(VOID); +typedef MTK_WCN_BOOL(*IS_AEE_DUMP_SUPPORT)(VOID); + + +typedef struct _WMT_IC_OPS_ { + UINT32 icId; + SW_INIT sw_init; + SW_DEINIT sw_deinit; + IC_PIN_CTRL ic_pin_ctrl; + IC_VER_CHECK ic_ver_check; + CO_CLOCK_CTRL co_clock_ctrl; + IS_QUICK_SLEEP_SUPPORT is_quick_sleep; + IS_AEE_DUMP_SUPPORT is_aee_dump_support; +} WMT_IC_OPS, *P_WMT_IC_OPS; + +typedef struct _WMT_CTX_ +{ + ENUM_DRV_STS eDrvStatus[WMTDRV_TYPE_MAX]; /* Controlled driver status */ + UINT32 wmtInfoBit; /* valid info bit */ + WMT_HIF_CONF wmtHifConf; /* HIF information */ + + /* Pointer to WMT_IC_OPS. Shall be assigned to a correct table in stp_init + * if and only if getting chip id successfully. hwver and fwver are kept in + * WMT-IC module only. + */ + P_WMT_IC_OPS p_ic_ops; +} WMT_CTX, *P_WMT_CTX; + +// TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. +// Using this struct relies on compiler's implementation and pack() settings +typedef struct _WMT_PKT_ { + UINT8 eType; // PKT_TYPE_* + UINT8 eOpCode; // OPCODE_* + UINT16 u2SduLen; // 2 bytes length, little endian + UINT8 aucParam[32]; +} WMT_PKT, *P_WMT_PKT; + +/* WMT Packet Format */ +typedef enum _ENUM_PKT_TYPE { + PKT_TYPE_INVALID = 0, + PKT_TYPE_CMD = 1, + PKT_TYPE_EVENT = 2, + PKT_TYPE_MAX +} ENUM_PKT_TYPE, *P_ENUM_PKT_TYPE; + +typedef enum _ENUM_OPCODE { + OPCODE_INVALID = 0, + OPCODE_PATCH = 1, + OPCODE_TEST = 2, + OPCODE_WAKEUP = 3, + OPCODE_HIF = 4, + OPCODE_STRAP_CONF = 5, + OPCODE_FUNC_CTRL = 6, + OPCODE_RESET = 7, + OPCODE_INT = 8, + OPCODE_MAX +} ENUM_OPCODE, *P_ENUM_OPCODE; + +typedef enum { + WMT_STP_CONF_EN = 0, + WMT_STP_CONF_RDY = 1, + WMT_STP_CONF_MODE = 2, + WMT_STP_CONF_MAX +} WMT_STP_CONF_TYPE; + +struct init_script { + UCHAR *cmd; + UINT32 cmdSz; + UCHAR *evt; + UINT32 evtSz; + UCHAR *str; +}; + +typedef struct _WMT_PATCH { + UINT8 ucDateTime[16]; + UINT8 ucPLat[4]; + UINT16 u2HwVer; + UINT16 u2SwVer; + UINT32 u4PatchVer; +} WMT_PATCH, *P_WMT_PATCH; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern INT32 wmt_core_init(VOID); +extern INT32 wmt_core_deinit(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmtd +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 +wmt_core_opid ( + P_WMT_OP pWmtOp + ); + +extern INT32 +wmt_core_ctrl ( + ENUM_WMT_CTRL_T ctrId, + PUINT32 pPa1, + PUINT32 pPa2 + ); + +extern INT32 +wmt_core_func_ctrl_cmd ( + ENUM_WMTDRV_TYPE_T type, + MTK_WCN_BOOL fgEn + ); + +extern INT32 +wmt_core_reg_rw_raw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pVal, + UINT32 mask +); + +extern VOID +wmt_core_dump_data ( + PUINT8 pData, + PUINT8 pTitle, + UINT32 len + ); + +extern MTK_WCN_BOOL +wmt_core_patch_check ( + UINT32 u4PatchVer, + UINT32 u4HwVer + ); + +extern INT32 +wmt_core_init_script ( + struct init_script *script, + INT32 count + ); + +extern INT32 +wmt_core_rx ( + PUINT8 pBuf, + UINT32 bufLen, + UINT32 *readSize + ); + +extern INT32 +wmt_core_tx ( + const UINT8 *pData, + UINT32 size, + UINT32 *writtenSize, + MTK_WCN_BOOL bRawFlag + ); +extern MTK_WCN_BOOL wmt_core_is_quick_ps_support (void); + +extern MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static _osal_inline_ MTK_WCN_BOOL +wmt_core_ic_ops_check ( + P_WMT_IC_OPS p_ops + ) +{ + if (!p_ops) { + return MTK_WCN_BOOL_FALSE; + } + if ( (NULL == p_ops->sw_init) + || (NULL == p_ops->sw_deinit) + || (NULL == p_ops->ic_ver_check) + || (NULL == p_ops->ic_pin_ctrl) ) { + return MTK_WCN_BOOL_FALSE; + } + else { + return MTK_WCN_BOOL_TRUE; + } +} + +#endif /* _WMT_CORE_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_ctrl.h b/drivers/mtk_wcn_combo/common/core/include/wmt_ctrl.h new file mode 100755 index 000000000000..4f1b196844ca --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_ctrl.h @@ -0,0 +1,135 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_CTRL_H_ +#define _WMT_CTRL_H_ + +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define DWCNT_CTRL_DATA (16) + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _WMT_CTRL_DATA_ { + UINT32 ctrlId; + UINT32 au4CtrlData[DWCNT_CTRL_DATA]; +} WMT_CTRL_DATA, *P_WMT_CTRL_DATA; + +typedef enum _ENUM_WMT_CTRL_T { + WMT_CTRL_HW_PWR_OFF = 0, /* whole chip power off */ + WMT_CTRL_HW_PWR_ON = 1, /* whole chip power on */ + WMT_CTRL_HW_RST = 2,/* whole chip power on */ + WMT_CTRL_STP_CLOSE = 3, + WMT_CTRL_STP_OPEN = 4, + WMT_CTRL_STP_CONF = 5, + WMT_CTRL_FREE_PATCH = 6, + WMT_CTRL_GET_PATCH = 7, + WMT_CTRL_GET_PATCH_NAME = 8, + WMT_CTRL_HOST_BAUDRATE_SET = 9, + WMT_CTRL_SDIO_HW = 10, /* enable/disable SDIO1/2 of combo chip */ + WMT_CTRL_SDIO_FUNC = 11, /* probe/remove STP/Wi-Fi driver in SDIO1/2 of combo chip*/ + WMT_CTRL_HWIDVER_SET = 12, // TODO: rename this and add chip id information in addition to chip version + WMT_CTRL_HWVER_GET = 13, // TODO: [FixMe][GeorgeKuo] remove unused functions + WMT_CTRL_STP_RST = 14, + WMT_CTRL_GET_WMT_CONF = 15, + WMT_CTRL_TX = 16, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ + WMT_CTRL_RX = 17, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ + WMT_CTRL_RX_FLUSH = 18, /* [FixMe][SeanWang]: to be removed by Sean's stp integration */ + WMT_CTRL_GPS_SYNC_SET = 19, + WMT_CTRL_GPS_LNA_SET = 20, + WMT_CTRL_PATCH_SEARCH = 21, + WMT_CTRL_CRYSTAL_TRIMING_GET = 22, + WMT_CTRL_CRYSTAL_TRIMING_PUT = 23, + WMT_CTRL_HW_STATE_DUMP = 24, + WMT_CTRL_GET_PATCH_NUM = 25, + WMT_CTRL_GET_PATCH_INFO = 26, + WMT_CTRL_MAX +} ENUM_WMT_CTRL_T, *P_ENUM_WMT_CTRL_T; + +typedef INT32 (*WMT_CTRL_FUNC)(P_WMT_CTRL_DATA); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern INT32 +wmt_ctrl ( + P_WMT_CTRL_DATA pWmtCtrlData + ); + +extern INT32 +wmt_ctrl_tx_ex ( + const UINT8 *pData, + const UINT32 size, + UINT32 *writtenSize, + const MTK_WCN_BOOL bRawFlag + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + +#endif /* _WMT_CTRL_H_ */ + + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h b/drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h new file mode 100755 index 000000000000..33fd494ba4bf --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h @@ -0,0 +1,48 @@ + +#ifndef _WMT_DBG_H_ +#define _WMT_DBG_H_ +#include "osal.h" + +#define STP_SDIO 0x04 +#define STP_UART_MAND 0x02 +#define STP_UART_FULL 0x01 + +#define CFG_WMT_DBG_SUPPORT 1 // support wmt_dbg or not + +#if CFG_WMT_DBG_SUPPORT +typedef struct _COEX_BUF{ + UINT8 buffer[128]; + INT32 availSize; +}COEX_BUF, *P_COEX_BUF; + +typedef enum _ENUM_CMD_TYPE_T { + WMTDRV_CMD_ASSERT = 0, + WMTDRV_CMD_EXCEPTION = 1, + WMTDRV_CMD_COEXDBG_00 = 2, + WMTDRV_CMD_COEXDBG_01 = 3, + WMTDRV_CMD_COEXDBG_02 = 4, + WMTDRV_CMD_COEXDBG_03 = 5, + WMTDRV_CMD_COEXDBG_04 = 6, + WMTDRV_CMD_COEXDBG_05 = 7, + WMTDRV_CMD_COEXDBG_06 = 8, + WMTDRV_CMD_COEXDBG_07 = 9, + WMTDRV_CMD_COEXDBG_08 = 10, + WMTDRV_CMD_COEXDBG_09 = 11, + WMTDRV_CMD_COEXDBG_10 = 12, + WMTDRV_CMD_COEXDBG_11 = 13, + WMTDRV_CMD_COEXDBG_12 = 14, + WMTDRV_CMD_COEXDBG_13 = 15, + WMTDRV_CMD_COEXDBG_14 = 16, + WMTDRV_CMD_COEXDBG_15 = 17, + WMTDRV_CMD_MAX +} ENUM_WMTDRV_CMD_T, *P_ENUM_WMTDRV_CMD_T; + + +typedef INT32 (*WMT_DEV_DBG_FUNC)(INT32 par1, INT32 par2, INT32 par3); +INT32 wmt_dev_dbg_setup(VOID); +INT32 wmt_dev_dbg_remove(VOID); + + +#endif + +#endif diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_func.h b/drivers/mtk_wcn_combo/common/core/include/wmt_func.h new file mode 100755 index 000000000000..a04bcda4d2aa --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_func.h @@ -0,0 +1,134 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_FUNC_H_ +#define _WMT_FUNC_H_ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_core.h" +#include "wmt_plat.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if 1//defined(CONFIG_MTK_COMBO_HCI_DRIVER) || defined(CONFIG_MTK_COMBO_BT) +#define CFG_FUNC_BT_SUPPORT 1 +#else +#define CFG_FUNC_BT_SUPPORT 0 +#endif + + +#if 1//defined(CONFIG_MTK_COMBO_FM) +#define CFG_FUNC_FM_SUPPORT 1 +#else +#define CFG_FUNC_FM_SUPPORT 0 +#endif + +#if 1//defined(CONFIG_MTK_COMBO_GPS) +#define CFG_FUNC_GPS_SUPPORT 1 +#else +#define CFG_FUNC_GPS_SUPPORT 0 +#endif + +#if 1//defined(CONFIG_MTK_COMBO_WIFI) +#define CFG_FUNC_WIFI_SUPPORT 1 +#else +#define CFG_FUNC_WIFI_SUPPORT 0 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef INT32 (*SUBSYS_FUNC_ON)(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +typedef INT32 (*SUBSYS_FUNC_OFF)(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +typedef struct _WMT_FUNC_OPS_{ + SUBSYS_FUNC_ON func_on; + SUBSYS_FUNC_OFF func_off; +}WMT_FUNC_OPS, *P_WMT_FUNC_OPS; + +typedef struct _CMB_PIN_CTRL_REG_ +{ + UINT32 regAddr; + UINT32 regValue; + UINT32 regMask; + +}CMB_PIN_CTRL_REG, *P_CMB_PIN_CTRL_REG; + +typedef struct _CMB_PIN_CTRL_ +{ + UINT32 pinId; + UINT32 regNum; + P_CMB_PIN_CTRL_REG pFuncOnArray; + P_CMB_PIN_CTRL_REG pFuncOffArray; + +}CMB_PIN_CTRL, *P_CMB_PIN_CTRL; + +typedef enum _ENUM_CMP_PIN_ID_{ + CMB_PIN_EEDI_ID = 0, + CMB_PIN_EEDO_ID = 1, + CMB_PIN_GSYNC_ID = 2, +}ENUM_CMP_PIN_ID, *P_ENUM_CMP_PIN_ID; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + + + + + +#endif /* _WMT_FUNC_H_ */ + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_ic.h b/drivers/mtk_wcn_combo/common/core/include/wmt_ic.h new file mode 100755 index 000000000000..1f857c4d6620 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_ic.h @@ -0,0 +1,113 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_IC_H_ +#define _WMT_IC_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "wmt_core.h" +#include "wmt_exp.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WMT_IC_NAME_MT6620 "MT6620" +#define WMT_IC_NAME_MT6628 "MT6628" + + +#define WMT_IC_VER_E1 "E1" +#define WMT_IC_VER_E2 "E2" +#define WMT_IC_VER_E3 "E3" +#define WMT_IC_VER_E4 "E4" +#define WMT_IC_VER_E5 "E5" +#define WMT_IC_VER_E6 "E6" +#define WMT_IC_VER_E7 "E7" + +#define WMT_IC_PATCH_DUMMY_EXT "_ex" +#define WMT_IC_PATCH_NO_EXT "" +#define WMT_IC_PATCH_E1_EXT "_e1" +#define WMT_IC_PATCH_E2_EXT "_e2" +#define WMT_IC_PATCH_E3_EXT "_e3" +#define WMT_IC_PATCH_E4_EXT "_e4" +#define WMT_IC_PATCH_E5_EXT "_e5" +#define WMT_IC_PATCH_E6_EXT "_e6" + +#define WMT_IC_PATCH_TAIL "_hdr.bin" + +#define WMT_IC_INVALID_CHIP_ID 0xFFFF + +#define MAJORNUM(x) (x & 0x00F0) +#define MINORNUM(x) (x & 0x000F) + +/******************************************************************************* +* R E G I S T E R M A P +******************************************************************************** +*/ +/* General definition used for ALL/UNKNOWN CHIPS */ +/* Now MT6620 uses these definitions */ +#define GEN_CONFG_BASE (0x80000000UL) +#define GEN_HVR (GEN_CONFG_BASE + 0x0UL) /* HW_VER */ +#define GEN_FVR (GEN_CONFG_BASE + 0x4UL) /* FW_VER */ +#define GEN_VER_MASK (0x0000FFFFUL) /* HW_VER and FW_VER valid bits mask */ +#define GEN_HCR (GEN_CONFG_BASE + 0x8UL) /* HW_CODE, chip id */ +#define GEN_HCR_MASK (0x0000FFFFUL) /* HW_CODE valid bits mask */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _WMT_IC_INFO_S +{ + UINT32 u4HwVer; /* u4HwId */ + PUINT8 cChipName; + PUINT8 cChipVersion; + PUINT8 cPatchNameExt; + MTK_WCN_BOOL bPsmSupport; + MTK_WCN_BOOL bWorkWithoutPatch; + ENUM_WMTHWVER_TYPE_T eWmtHwVer; +} WMT_IC_INFO_S, *P_WMT_IC_INFO_S; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_IC_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_lib.h b/drivers/mtk_wcn_combo/common/core/include/wmt_lib.h new file mode 100755 index 000000000000..c40349a33079 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/include/wmt_lib.h @@ -0,0 +1,327 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_LIB_H_ +#define _WMT_LIB_H_ + +#include "osal.h" +#include "wmt_core.h" +#include "wmt_exp.h" +#include +#include "stp_wmt.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define WMT_OP_BUF_SIZE (16) +#if 0 /* moved to wmt_exp.h */ +#define WMT_LOG_LOUD 4 +#define WMT_LOG_DBG 3 +#define WMT_LOG_INFO 2 +#define WMT_LOG_WARN 1 +#define WMT_LOG_ERR 0 +#endif +typedef enum _ENUM_WMTRSTRET_TYPE_T{ + WMTRSTRET_SUCCESS = 0x0, + WMTRSTRET_FAIL = 0x1, + WMTRSTRET_ONGOING = 0x2, + WMTRSTRET_MAX +} ENUM_WMTRSTRET_TYPE_T, *P_ENUM_WMTRSTRET_TYPE_T; + +/* +3(retry times) * 180 (STP retry time out) ++ 10 (firmware process time) + +10 (transmit time) + +10 (uart process -> WMT response pool) + +230 (others) +*/ +#define WMT_LIB_RX_TIMEOUT 2000/*800-->cover v1.2phone BT function on time (~830ms)*/ +/* +open wifi during wifi power on procedure +(because wlan is insert to system after mtk_hif_sdio module, +so wifi card is not registered to hif module +when mtk_wcn_wmt_func_on is called by wifi through rfkill) +*/ +#define MAX_WIFI_ON_TIME 5500 + +#define WMT_PWRON_RTY_DFT 2 +#define MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT WMT_PWRON_RTY_DFT * WMT_LIB_RX_TIMEOUT +#define MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY WMT_LIB_RX_TIMEOUT /*each WMT command*/ +#define MAX_FUNC_ON_TIME (MAX_WIFI_ON_TIME + MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT + MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY * 3) + +#define MAX_EACH_FUNC_OFF WMT_LIB_RX_TIMEOUT + 1000 /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement*/ +#define MAX_FUNC_OFF_TIME MAX_EACH_FUNC_OFF * 4 + +#define MAX_EACH_WMT_CMD WMT_LIB_RX_TIMEOUT + 1000 /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement*/ + +#define MAX_GPIO_CTRL_TIME (2000) /* [FixMe][GeorgeKuo] a temp value */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if 0 /* moved to wmt_exp.h */ +/* FIXME: apply KERN_* definition? */ +extern UINT32 gWmtDbgLvl ; +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_LOUD_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_LOUD) { osal_dbg_print(DFT_TAG "[L]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_INFO_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_INFO) { osal_info_print(DFT_TAG "[I]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_WARN_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_WARN) { osal_warn_print(DFT_TAG "[W]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_ERR_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_ERR) { osal_err_print(DFT_TAG "[E]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} +#define WMT_DBG_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "[D]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_TRC_FUNC(f) if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "<%s> <%d>\n", __FUNCTION__, __LINE__);} +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* AIF FLAG definition */ +/* bit(0): share pin or not */ +#define WMT_LIB_AIF_FLAG_MASK (0x1UL) +#define WMT_LIB_AIF_FLAG_SHARE (0x1UL << 0) +#define WMT_LIB_AIF_FLAG_SEPARATE (0x0UL << 0) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* bit field offset definition */ +typedef enum { + WMT_STAT_PWR = 0, /* is powered on */ + WMT_STAT_STP_REG = 1, /* is STP driver registered: */ + WMT_STAT_STP_OPEN = 2, /* is STP opened: default FALSE*/ + WMT_STAT_STP_EN = 3, /* is STP enabled: default FALSE*/ + WMT_STAT_STP_RDY = 4, /* is STP ready for client: default FALSE*/ + WMT_STAT_RX = 5, /* is rx data available */ + WMT_STAT_CMD = 6, /* is cmd string to be read */ + WMT_STAT_SDIO1_ON = 7, /* is SDIO1 on */ + WMT_STAT_SDIO2_ON = 8, /* is SDIO2 on */ + WMT_STAT_SDIO_WIFI_ON = 9, /* is Wi-Fi SDIO function on */ + WMT_STAT_SDIO_STP_ON = 10, /* is STP SDIO function on */ + WMT_STAT_RST_ON = 11, + WMT_STAT_MAX +} WMT_STAT; + +typedef enum _ENUM_WMTRSTSRC_TYPE_T{ + WMTRSTSRC_RESET_BT = 0x0, + WMTRSTSRC_RESET_FM = 0x1, + WMTRSTSRC_RESET_GPS = 0x2, + WMTRSTSRC_RESET_WIFI = 0x3, + WMTRSTSRC_RESET_STP = 0x4, + WMTRSTSRC_RESET_TEST = 0x5, + WMTRSTSRC_RESET_MAX +} ENUM_WMTRSTSRC_TYPE_T, *P_ENUM_WMTRSTSRC_TYPE_T; + + +typedef struct { + PF_WMT_CB fDrvRst[4]; +} WMT_FDRV_CB, *P_WMT_FDRV_CB; + + +typedef struct { + UINT32 dowloadSeq; + UCHAR addRess[4]; + UCHAR patchName[256]; +}WMT_PATCH_INFO,*P_WMT_PATCH_INFO; + + +/* OS independent wrapper for WMT_OP */ +typedef struct _DEV_WMT_ { + + OSAL_SLEEPABLE_LOCK psm_lock; + /* WMTd thread information */ +// struct task_struct *pWmtd; /* main thread (wmtd) handle */ + OSAL_THREAD thread; +// wait_queue_head_t rWmtdWq; /*WMTd command wait queue */ + OSAL_EVENT rWmtdWq; //rename + //ULONG state; /* bit field of WMT_STAT */ + OSAL_BIT_OP_VAR state; + + /* STP context information */ +// wait_queue_head_t rWmtRxWq; /* STP Rx wait queue */ + OSAL_EVENT rWmtRxWq; //rename +// WMT_STP_FUNC rStpFunc; /* STP functions */ + WMT_FDRV_CB rFdrvCb; + + /* WMT Configurations */ + WMT_HIF_CONF rWmtHifConf; + WMT_GEN_CONF rWmtGenConf; + + /* Patch information */ + UCHAR cPatchName[NAME_MAX + 1]; + UCHAR cFullPatchName[NAME_MAX + 1]; + UINT32 patchNum; + const osal_firmware *pPatch; + + UCHAR cWmtcfgName[NAME_MAX + 1]; + const osal_firmware *pWmtCfg; + + const osal_firmware *pNvram; + + /* Current used UART port description*/ + CHAR cUartName[NAME_MAX + 1]; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[WMT_OP_BUF_SIZE]; /* real op instances */ + P_OSAL_OP pCurOP; /* current op*/ + + /* cmd str buffer */ + UCHAR cCmd[NAME_MAX + 1]; + INT32 cmdResult; +// struct completion cmd_comp; +// wait_queue_head_t cmd_wq; /* read command queues */ + OSAL_SIGNAL cmdResp; + OSAL_EVENT cmdReq; + + /* WMT loopback Thread Information */ +// WMT_CMB_VER combo_ver; + //P_WMT_CMB_CHIP_INFO_S pChipInfo; + UINT32 chip_id; + UINT32 hw_ver; + UINT32 fw_ver; + // TODO: [FixMe][GeorgeKuo] remove this translated version code in the + // future. Just return the above 3 info to querist + ENUM_WMTHWVER_TYPE_T eWmtHwVer; + + P_WMT_PATCH_INFO pWmtPatchInfo; +}DEV_WMT, *P_DEV_WMT; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +extern INT32 wmt_lib_init(VOID); +extern INT32 wmt_lib_deinit(VOID); +extern INT32 wmt_lib_tx (UINT8 *data, UINT32 size, UINT32 *writtenSize); +extern INT32 wmt_lib_tx_raw (UINT8 *data, UINT32 size, UINT32 *writtenSize); +extern INT32 wmt_lib_rx(UINT8 *buff, UINT32 buffLen, UINT32 *readSize); +extern VOID +wmt_lib_flush_rx(VOID); + +#if CFG_WMT_PS_SUPPORT +extern INT32 +wmt_lib_ps_set_idle_time(UINT32 psIdleTime); +extern INT32 +wmt_lib_ps_init(VOID); +extern INT32 +wmt_lib_ps_deinit(VOID); +extern INT32 +wmt_lib_ps_enable(VOID); +extern INT32 +wmt_lib_ps_ctrl(UINT32 state); + +extern INT32 +wmt_lib_ps_disable(VOID); +extern VOID +wmt_lib_ps_irq_cb(VOID); +#endif +extern VOID +wmt_lib_ps_set_sdio_psop ( + PF_WMT_SDIO_PSOP own_cb + ); + +/* LXOP functions: */ +extern P_OSAL_OP wmt_lib_get_free_op (VOID); +extern INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp); +extern MTK_WCN_BOOL wmt_lib_put_act_op (P_OSAL_OP pOp); + +//extern ENUM_WMTHWVER_TYPE_T wmt_lib_get_hwver (VOID); +extern UINT32 wmt_lib_get_icinfo (ENUM_WMT_CHIPINFO_TYPE_T type); + +extern MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support (VOID); +extern MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support (VOID); +extern INT32 wmt_lib_trigger_cmd_signal (INT32 result); +extern UCHAR *wmt_lib_get_cmd(VOID); +extern P_OSAL_EVENT wmt_lib_get_cmd_event(VOID); +extern INT32 wmt_lib_set_patch_name(UCHAR *cPatchName); +extern INT32 wmt_lib_set_uart_name(CHAR *cUartName); +extern INT32 wmt_lib_set_hif(ULONG hifconf); +extern P_WMT_HIF_CONF wmt_lib_get_hif(VOID); +extern MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID); + +/* GeorgeKuo: replace set_chip_gpio() with more specific ones */ +#if 0/* moved to wmt_exp.h */ +extern INT32 wmt_lib_set_aif (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ +#endif +extern INT32 wmt_lib_host_awake_get(VOID); +extern INT32 wmt_lib_host_awake_put(VOID); +extern UINT32 wmt_lib_dbg_level_set(UINT32 level); + +extern INT32 wmt_lib_msgcb_reg ( + ENUM_WMTDRV_TYPE_T eType, + PF_WMT_CB pCb + ); + +extern INT32 wmt_lib_msgcb_unreg ( + ENUM_WMTDRV_TYPE_T eType + ); +ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst( ENUM_WMTRSTSRC_TYPE_T src); +MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst); +MTK_WCN_BOOL wmt_lib_hw_rst(VOID); +INT32 wmt_lib_reg_rw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pvalue, + UINT32 mask + ); +INT32 wmt_lib_efuse_rw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pvalue, + UINT32 mask + ); +INT32 wmt_lib_sdio_ctrl(UINT32 on); + +extern INT32 DISABLE_PSM_MONITOR(void); +extern VOID ENABLE_PSM_MONITOR(void); +extern INT32 wmt_lib_notify_stp_sleep(void); +extern void wmt_lib_psm_lock_release(void); +extern INT32 wmt_lib_psm_lock_aquire(void); +extern INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value); + +extern VOID wmt_lib_set_patch_num(ULONG num); +extern VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo); + +extern INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp); +extern P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev); + +extern INT32 wmt_lib_merge_if_flag_ctrl(UINT32 enable); +extern INT32 wmt_lib_merge_if_flag_get(UINT32 enable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_LIB_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/core/psm_core.c b/drivers/mtk_wcn_combo/common/core/psm_core.c new file mode 100755 index 000000000000..38165f0d5b00 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/psm_core.c @@ -0,0 +1,2005 @@ +#include "osal_typedef.h" +#include "osal.h" +#include "psm_core.h" +#include "stp_core.h" +#include + +INT32 gPsmDbgLevel = STP_PSM_LOG_INFO; +MTKSTP_PSM_T stp_psm_i; +MTKSTP_PSM_T *stp_psm = &stp_psm_i; + +#define STP_PSM_LOUD_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_LOUD){ osal_dbg_print(PFX_PSM "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_PSM_DBG_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_DBG){ osal_dbg_print(PFX_PSM "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_PSM_INFO_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_INFO){ osal_dbg_print(PFX_PSM "[I]%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_PSM_WARN_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_WARN){ osal_dbg_print(PFX_PSM "[W]%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_PSM_ERR_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_ERR){ osal_dbg_print(PFX_PSM "[E]%s(%d):ERROR! " fmt, __FUNCTION__ , __LINE__, ##arg);} +#define STP_PSM_TRC_FUNC(f) if(gPsmDbgLevel >= STP_PSM_LOG_DBG){ osal_dbg_print(PFX_PSM "<%s> <%d>\n", __FUNCTION__, __LINE__);} + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +static INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); +static INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); + +static const PCHAR g_psm_state[STP_PSM_MAX_STATE] = { + "ACT", + "ACT_INACT", + "INACT", + "INACT_ACT" +}; + +static const PCHAR g_psm_action[STP_PSM_MAX_ACTION] = { + "SLEEP" , + "HOST_AWAKE", + "WAKEUP", + "EIRQ", + "ROLL_BACK" +}; + +static const PCHAR g_psm_op_name[STP_OPID_PSM_NUM] = { + "STP_OPID_PSM_SLEEP", + "STP_OPID_PSM_WAKEUP", + "STP_OPID_PSM_HOST_AWAKE", + "STP_OPID_PSM_EXIT" +}; + +INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm); + +static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm); + +static INT32 _stp_psm_is_redundant_active_op( + P_OSAL_OP pOp, + P_OSAL_OP_Q pOpQ +); + +static INT32 _stp_psm_clean_up_redundant_active_op( + P_OSAL_OP_Q pOpQ + ); +static MTK_WCN_BOOL _stp_psm_is_quick_ps_support (VOID); +extern void mt_combo_plt_enter_deep_idle ( + COMBO_IF src + ) ; + +extern void mt_combo_plt_exit_deep_idle ( + COMBO_IF src + ) ; +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel) +{ + if (0 <= dbglevel && dbglevel <= 4) + { + gPsmDbgLevel = dbglevel; + STP_PSM_INFO_FUNC("gPsmDbgLevel = %d\n", gPsmDbgLevel); + return true; + } + else + { + STP_PSM_INFO_FUNC("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel); + } + return false; +} + +/* change from macro to static function to enforce type checking on parameters. */ +static INT32 psm_fifo_lock_init (MTKSTP_PSM_T *psm) +{ + + +#if CFG_PSM_CORE_FIFO_SPIN_LOCK + #if defined(CONFIG_PROVE_LOCKING) + osal_unsleepable_lock_init(&(psm->hold_fifo_lock)); + return 0; + #else + return osal_unsleepable_lock_init(&(psm->hold_fifo_lock)); + #endif +#else +#if defined(CONFIG_PROVE_LOCKING) + osal_sleepable_lock_init(&(psm->hold_fifo_lock)); + return 0; +#else + return osal_sleepable_lock_init(&(psm->hold_fifo_lock)); +#endif +#endif +} + +static INT32 psm_fifo_lock_deinit (MTKSTP_PSM_T *psm) +{ +#if CFG_PSM_CORE_FIFO_SPIN_LOCK + return osal_unsleepable_lock_deinit(&(psm->hold_fifo_lock)); +#else + return osal_sleepable_lock_deinit(&(psm->hold_fifo_lock)); +#endif +} + +static INT32 psm_fifo_lock (MTKSTP_PSM_T *psm) +{ + + +#if CFG_PSM_CORE_FIFO_SPIN_LOCK + return osal_lock_unsleepable_lock(&(psm->hold_fifo_lock)); +#else + return osal_lock_sleepable_lock(&(psm->hold_fifo_lock)); +#endif +} + +static INT32 psm_fifo_unlock (MTKSTP_PSM_T *psm) +{ + + +#if CFG_PSM_CORE_FIFO_SPIN_LOCK + return osal_unlock_unsleepable_lock(&(psm->hold_fifo_lock)); +#else + return osal_unlock_sleepable_lock(&(psm->hold_fifo_lock)); +#endif +} + +static INT32 _stp_psm_handler(MTKSTP_PSM_T *stp_psm, P_STP_OP pStpOp) +{ + INT32 ret = -1; + + //if (NULL == pStpOp) + //{ + // return -1; + //} + ret = _stp_psm_thread_lock_aquire(stp_psm); + if (ret) { + STP_PSM_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + switch(pStpOp->opId) + { + case STP_OPID_PSM_EXIT: + // TODO: clean all up? + ret = 0; + break; + + case STP_OPID_PSM_SLEEP: + if (stp_psm_check_sleep_enable(stp_psm) > 0) { + ret =_stp_psm_notify_wmt(stp_psm, SLEEP); + } else { + STP_PSM_INFO_FUNC("cancel sleep request\n"); + } + break; + + case STP_OPID_PSM_WAKEUP: + ret = _stp_psm_notify_wmt(stp_psm, WAKEUP); + break; + + case STP_OPID_PSM_HOST_AWAKE: + ret = _stp_psm_notify_wmt(stp_psm, HOST_AWAKE); + break; + + default: + STP_PSM_ERR_FUNC("invalid operation id (%d)\n", pStpOp->opId); + ret = -1; + break; + } + _stp_psm_thread_lock_release(stp_psm); + return ret; +} + +static P_OSAL_OP _stp_psm_get_op ( + MTKSTP_PSM_T *stp_psm, + P_OSAL_OP_Q pOpQ + ) +{ + P_OSAL_OP pOp; + + if (!pOpQ) + { + STP_PSM_WARN_FUNC("pOpQ == NULL\n"); + return NULL; + } + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* acquire lock success */ + RB_GET(pOpQ, pOp); + + if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) + { + //stp_psm->current_active_op = pOp;//*(pOp); + stp_psm->last_active_opId = pOp->op.opId; + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) + { + STP_PSM_DBG_FUNC("last_active_opId(%d)\n", stp_psm->last_active_opId); + } + + if (!pOp) + { + STP_PSM_WARN_FUNC("RB_GET fail\n"); + } + + return pOp; +} + +static INT32 _stp_psm_dump_active_q( + P_OSAL_OP_Q pOpQ +) +{ + UINT32 read_idx; + UINT32 write_idx; + UINT32 opId; + + if(pOpQ == &stp_psm->rActiveOpQ) + { + read_idx = stp_psm->rActiveOpQ.read; + write_idx = stp_psm->rActiveOpQ.write; + + STP_PSM_DBG_FUNC("Active op list:++\n"); + while ((read_idx & RB_MASK(pOpQ)) != (write_idx & RB_MASK(pOpQ))) + { + opId = pOpQ->queue[read_idx & RB_MASK(pOpQ)]->op.opId; + if(opId < STP_OPID_PSM_NUM) + { + STP_PSM_DBG_FUNC("%s\n", g_psm_op_name[opId] ); + } + else + { + STP_PSM_WARN_FUNC("Unkown OP Id\n"); + } + ++read_idx; + } + STP_PSM_DBG_FUNC("Active op list:--\n"); + } + else + { + STP_PSM_DBG_FUNC("%s: not active queue, dont dump\n", __func__); + } + + return 0; +} + +static INT32 _stp_psm_is_redundant_active_op( + P_OSAL_OP pOp, + P_OSAL_OP_Q pOpQ +) +{ + UINT32 opId = 0; + UINT32 prev_opId = 0; + + //if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != stp_psm->current_active_op)) + if((pOpQ == &stp_psm->rActiveOpQ) && (STP_OPID_PSM_INALID != stp_psm->last_active_opId)) + + { + opId = pOp->op.opId; + + if(opId == STP_OPID_PSM_SLEEP) + { + if(RB_EMPTY(pOpQ)) + { + //prev_opId = stp_psm->current_active_op->op.opId; + prev_opId = stp_psm->last_active_opId; + } + else + { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + } + + if(prev_opId == STP_OPID_PSM_SLEEP) + { + STP_PSM_DBG_FUNC("redundant sleep opId found\n"); + return 1; + } + else + { + return 0; + } + } + else + { + if(RB_EMPTY(pOpQ)) + { + //prev_opId = stp_psm->current_active_op->op.opId; + prev_opId = stp_psm->last_active_opId; + } + else + { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + } + + if(((opId== STP_OPID_PSM_WAKEUP) && ( prev_opId == STP_OPID_PSM_WAKEUP)) || + ((opId == STP_OPID_PSM_HOST_AWAKE) && ( prev_opId == STP_OPID_PSM_WAKEUP)) || + ((opId == STP_OPID_PSM_HOST_AWAKE) && ( prev_opId == STP_OPID_PSM_HOST_AWAKE)) || + ((opId == STP_OPID_PSM_WAKEUP) && ( prev_opId == STP_OPID_PSM_HOST_AWAKE)) + ) + { + STP_PSM_DBG_FUNC("redundant opId found, opId(%d), preOpid(%d)\n", opId, prev_opId); + return 1; + } + else + { + return 0; + } + } + } + else + { + return 0; + } + +} + +static INT32 _stp_psm_clean_up_redundant_active_op( + P_OSAL_OP_Q pOpQ + ) +{ + UINT32 prev_opId = 0; + UINT32 prev_prev_opId = 0; + + P_OSAL_OP pOp; + P_OSAL_OP_Q pFreeOpQ= &stp_psm->rFreeOpQ; + + if(pOpQ == &stp_psm->rActiveOpQ) + { + // sleep , wakeup | sleep, --> null | sleep (x) + // wakeup , sleep , wakeup | sleep --> wakeup | sleep (v) + // sleep , wakeup , sleep | wakeup --> sleep | wakeup (v) + // xxx, sleep | sleep --> xxx, sleep (v) + // xxx, wakeup | wakeup --> xxx, wakeup (v) + // xxx, awake | awake --> xxx, awake (v) --> should never happen + while(RB_COUNT(pOpQ) > 2) + { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + prev_prev_opId = pOpQ->queue[(pOpQ->write - 2) & RB_MASK(pOpQ)]->op.opId; + + if((prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_WAKEUP)|| + (prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_HOST_AWAKE) || + (prev_opId == STP_OPID_PSM_WAKEUP&& prev_prev_opId == STP_OPID_PSM_SLEEP) || + (prev_opId == STP_OPID_PSM_HOST_AWAKE&& prev_prev_opId == STP_OPID_PSM_SLEEP) + ) + { + RB_GET(pOpQ, pOp); + RB_PUT(pFreeOpQ, pOp); + RB_GET(pOpQ, pOp); + RB_PUT(pFreeOpQ, pOp); + } + else if (prev_opId == prev_prev_opId) + { + RB_GET(pOpQ, pOp); + STP_PSM_DBG_FUNC("redundant opId(%d) found, remove it\n", pOp->op.opId); + RB_PUT(pFreeOpQ, pOp); + } + } + } + + return 0; +} + +static INT32 _stp_psm_put_op ( + MTKSTP_PSM_T *stp_psm, + P_OSAL_OP_Q pOpQ, + P_OSAL_OP pOp + ) +{ + INT32 ret; + + // if (!pOpQ || !pOp) + // { + // STP_PSM_WARN_FUNC("pOpQ = 0x%p, pLxOp = 0x%p \n", pOpQ, pOp); + // return 0; + // } + ret = 0; + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* acquire lock success */ + if(pOpQ == &stp_psm->rActiveOpQ) + { + if(!_stp_psm_is_redundant_active_op(pOp, pOpQ)) + { + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + { + RB_PUT(pOpQ, pOp); + STP_PSM_DBG_FUNC("opId(%d) enqueue\n", pOp->op.opId); + } + else + { + STP_PSM_INFO_FUNC("************ Active Queue Full ************\n"); + ret = -1; + } + + _stp_psm_clean_up_redundant_active_op(pOpQ); + } + else + { + /*redundant opId, mark ret as success*/ + P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ; + if (!RB_FULL(pFreeOpQ)) + { + RB_PUT(pFreeOpQ, pOp); + } + else + { + osal_assert(!RB_FULL(pFreeOpQ)); + } + ret = 0; + } + } + else + { + if (!RB_FULL(pOpQ)) + { + RB_PUT(pOpQ, pOp); + } + else + { + ret = -1; + } + } + + if(pOpQ == &stp_psm->rActiveOpQ) + { + _stp_psm_dump_active_q(&stp_psm->rActiveOpQ); + } + + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + if (ret) + { + STP_PSM_WARN_FUNC("RB_FULL, RB_COUNT=%d , RB_SIZE=%d\n",RB_COUNT(pOpQ), RB_SIZE(pOpQ)); + return 0; + } + else + { + return 1; + } +} + +P_OSAL_OP _stp_psm_get_free_op ( + MTKSTP_PSM_T *stp_psm + ) +{ + P_OSAL_OP pOp; + + if (stp_psm) + { + pOp = _stp_psm_get_op(stp_psm, &stp_psm->rFreeOpQ); + if (pOp) + { + osal_memset(&pOp->op, 0, sizeof(pOp->op)); + } + return pOp; + } + else + { + return NULL; + } +} + +INT32 _stp_psm_put_act_op ( + MTKSTP_PSM_T *stp_psm, + P_OSAL_OP pOp + ) +{ + INT32 bRet = 0;//MTK_WCN_BOOL_FALSE; + INT32 bCleanup = 0;//MTK_WCN_BOOL_FALSE; + INT32 wait_ret = -1; + P_OSAL_SIGNAL pSignal = NULL; + + do + { + if (!stp_psm || !pOp) + { + STP_PSM_ERR_FUNC("stp_psm = %p, pOp = %p\n", stp_psm, pOp); + break; + } + + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) + { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* put to active Q */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rActiveOpQ, pOp); + + if(0 == bRet) + { + STP_PSM_WARN_FUNC("+++++++++++ Put op Active queue Fail\n"); + bCleanup = 1;//MTK_WCN_BOOL_TRUE; + break; + } + + /* wake up wmtd */ + osal_trigger_event(&stp_psm->STPd_event); + + if (pSignal->timeoutValue == 0) + { + bRet = 1;//MTK_WCN_BOOL_TRUE; + /* clean it in wmtd */ + break; + } + + /* wait result, clean it here */ + bCleanup = 1;//MTK_WCN_BOOL_TRUE; + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal); + STP_PSM_DBG_FUNC("wait completion:%d\n", wait_ret); + if (!wait_ret) + { + STP_PSM_ERR_FUNC("wait completion timeout \n"); + // TODO: how to handle it? retry? + } + else + { + if (pOp->result) + { + STP_PSM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); + } + /* op completes, check result */ + bRet = (pOp->result) ? 0 : 1; + } + } while(0); + + if (bCleanup) { + /* put Op back to freeQ */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp); + if(bRet == 0) + { + STP_PSM_WARN_FUNC("+++++++++++ Put op active free fail, maybe disable/enable psm\n"); + } + } + + return bRet; +} + +static INT32 _stp_psm_wait_for_msg(void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData; + STP_PSM_DBG_FUNC("%s: stp_psm->rActiveOpQ = %d\n", __func__, RB_COUNT(&stp_psm->rActiveOpQ)); + + return ((!RB_EMPTY(&stp_psm->rActiveOpQ)) || osal_thread_should_stop(&stp_psm->PSMd)); +} + +static INT32 _stp_psm_proc (void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData; + P_OSAL_OP pOp; + UINT32 id; + INT32 result; + + if (!stp_psm) { + STP_PSM_WARN_FUNC("!stp_psm \n"); + return -1; + } + +// STP_PSM_INFO_FUNC("wmtd starts running: pWmtDev(0x%p) [pol, rt_pri, n_pri, pri]=[%d, %d, %d, %d] \n", +// stp_psm, current->policy, current->rt_priority, current->normal_prio, current->prio); + + for (;;) { + + pOp = NULL; + + osal_wait_for_event(&stp_psm->STPd_event, + _stp_psm_wait_for_msg, + (void *)stp_psm); + + //we set reset flag when calling stp_reset after cleanup all op. + if(stp_psm->flag & STP_PSM_RESET_EN) + { + stp_psm->flag &= ~STP_PSM_RESET_EN; + } + + if (osal_thread_should_stop(&stp_psm->PSMd)) + { + STP_PSM_INFO_FUNC("should stop now... \n"); + // TODO: clean up active opQ + break; + } + + /* get Op from activeQ */ + pOp = _stp_psm_get_op(stp_psm, &stp_psm->rActiveOpQ); + if (!pOp) + { + STP_PSM_WARN_FUNC("+++++++++++ Get op from activeQ fail, maybe disable/enable psm\n"); + continue; + } + + id = osal_op_get_id(pOp); + + if (id >= STP_OPID_PSM_NUM) + { + STP_PSM_WARN_FUNC("abnormal opid id: 0x%x \n", id); + result = -1; + goto handler_done; + } + + result = _stp_psm_handler(stp_psm, &pOp->op); + +handler_done: + + if (result) + { + STP_PSM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, (id >= 4)?("???"):(g_psm_op_name[id]), result); + } + + if (osal_op_is_wait_for_signal(pOp)) + { + osal_op_raise_signal(pOp, result); + } + else + { + /* put Op back to freeQ */ + if(_stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp) == 0) + { + STP_PSM_WARN_FUNC("+++++++++++ Put op to FreeOpQ fail, maybe disable/enable psm\n"); + } + } + + if (STP_OPID_PSM_EXIT == id) + { + break; + } + } + STP_PSM_INFO_FUNC("exits \n"); + + return 0; +}; + +static inline INT32 _stp_psm_get_time(void) +{ + if(gPsmDbgLevel >= STP_PSM_LOG_LOUD) + { + osal_printtimeofday(">>>"); + } + + return 0; +} + +static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm) +{ + + if(stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + if(stp_psm->work_state < STP_PSM_MAX_STATE) + { + return stp_psm->work_state; + } + else + { + STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); + + return -STP_PSM_OPERATION_FAIL; + } + } +} + +static inline INT32 _stp_psm_set_state(MTKSTP_PSM_T *stp_psm,const MTKSTP_PSM_STATE_T state) +{ + if(stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + if(stp_psm->work_state < STP_PSM_MAX_STATE) + { + _stp_psm_get_time(); + //STP_PSM_INFO_FUNC("work_state = %s --> %s\n", g_psm_state[stp_psm->work_state], g_psm_state[state]); + + stp_psm->work_state = state; + if(stp_psm->work_state != ACT) + { +// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); + stp_psm->flag |= STP_PSM_BLOCK_DATA_EN; +// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); + } + } + else + { + STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); + } + } + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + + if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR)!= 0) + { + STP_PSM_DBG_FUNC("STP-PSM DISABLE, DONT restart monitor!\n\r"); + return STP_PSM_OPERATION_SUCCESS; + } + + + STP_PSM_LOUD_FUNC("start monitor\n"); + osal_timer_modify(&stp_psm->psm_timer, stp_psm->idle_time_to_sleep); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_stop_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + STP_PSM_DBG_FUNC("stop monitor\n"); + osal_timer_stop_sync(&stp_psm->psm_timer); + } + + return STP_PSM_OPERATION_SUCCESS; +} + +INT32 +_stp_psm_hold_data ( + MTKSTP_PSM_T *stp_psm, + const UINT8 *buffer, + const UINT32 len, + const UINT8 type + ) +{ + INT32 available_space = 0; + INT32 needed_space = 0; + UINT8 delimiter [] = {0xbb, 0xbb}; + + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + psm_fifo_lock(stp_psm); + + available_space = STP_PSM_FIFO_SIZE- osal_fifo_len(&stp_psm->hold_fifo); + needed_space = len + sizeof(UINT8) + sizeof(UINT32) + 2; + + //STP_PSM_INFO_FUNC("*******FIFO Available(%d), Need(%d)\n", available_space, needed_space); + + if( available_space < needed_space ) + { + STP_PSM_ERR_FUNC("FIFO Available!! Reset FIFO\n"); + osal_fifo_reset(&stp_psm->hold_fifo); + } + //type + osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) &type , sizeof(UINT8)); + //lenght + osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) &len , sizeof(UINT32)); + //buffer + osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) buffer, len); + //delimiter + osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) delimiter, 2); + + psm_fifo_unlock(stp_psm); + + return len; + } +} + +INT32 _stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) +{ + return osal_fifo_len(&stp_psm->hold_fifo); +} + +INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm) +{ + + INT32 i = 20; /*Max buffered packet number*/ + INT32 ret = 0; + UINT8 type = 0; + UINT32 len = 0; + UINT8 delimiter[2]; + + //STP_PSM_ERR_FUNC("++++++++++release data++len=%d\n", osal_fifo_len(&stp_psm->hold_fifo)); + while(osal_fifo_len(&stp_psm->hold_fifo) && i > 0) + { + //acquire spinlock + psm_fifo_lock(stp_psm); + + ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)&type, sizeof(UINT8)); + ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)&len, sizeof(UINT32)); + + if(len > STP_PSM_PACKET_SIZE_MAX) + { + STP_PSM_ERR_FUNC("***psm packet's length too Long!****\n"); + STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); + } + else + { + osal_memset(stp_psm->out_buf, 0, STP_PSM_TX_SIZE); + ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)stp_psm->out_buf, len); + } + + ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)delimiter, 2); + + if(delimiter[0]==0xbb && delimiter[1]==0xbb) + { + //osal_buffer_dump(stp_psm->out_buf, "psm->out_buf", len, 32); + stp_send_data_no_ps(stp_psm->out_buf, len, type); + } + else + { + STP_PSM_ERR_FUNC("***psm packet fifo parsing fail****\n"); + STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); + + osal_fifo_reset(&stp_psm->hold_fifo); + } + i--; + psm_fifo_unlock(stp_psm); + } + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_notify_wmt_host_awake_wq(MTKSTP_PSM_T *stp_psm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) + { + STP_PSM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + + pOp->op.opId = STP_OPID_PSM_HOST_AWAKE; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + + STP_PSM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0; + } + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_wakeup_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_psm == NULL) + { + return (STP_PSM_OPERATION_FAIL); + } + else + { + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) + { + STP_PSM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + + pOp->op.opId = STP_OPID_PSM_WAKEUP; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + if (0 == bRet) + { + STP_PSM_WARN_FUNC("OPID(%d) type(%d) bRet(%s)\n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + "fail"); + } + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : (STP_PSM_OPERATION_SUCCESS); + } + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_sleep_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if(stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY) != 0) + { + return 0; + } + + if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY) != 0) + { + return 0; + } + + if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR) != 0) + { + return 0; + } + + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_WARN_FUNC("get_free_lxop fail \n"); + return -1;//break; + } + + pOp->op.opId = STP_OPID_PSM_SLEEP; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + + STP_PSM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n", + pOp->op.opId, + pOp->op.au4OpData[0], + bRet); + + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0; + } + return retval; +} + +/*internal function*/ + +static inline INT32 _stp_psm_reset(MTKSTP_PSM_T *stp_psm) +{ + INT32 i = 0; + P_OSAL_OP_Q pOpQ; + P_OSAL_OP pOp; + INT32 ret = 0; + + STP_PSM_DBG_FUNC("PSM MODE RESET=============================>\n\r"); + + STP_PSM_INFO_FUNC("_stp_psm_reset\n"); + STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + //--> serialized the request from wmt <--// + ret = osal_lock_sleepable_lock(&stp_psm->user_lock); + if (ret) { + STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + + //--> disable psm <--// + stp_psm->flag = STP_PSM_WMT_EVENT_DISABLE_MONITOR; + _stp_psm_stop_monitor(stp_psm); + + //--> prepare the op list <--// + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); + RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); + + //stp_psm->current_active_op = NULL; + stp_psm->last_active_opId = STP_OPID_PSM_INALID; + + pOpQ = &stp_psm->rFreeOpQ; + for (i = 0; i < STP_OP_BUF_SIZE; i++) + { + if (!RB_FULL(pOpQ)) + { + pOp = &stp_psm->arQue[i]; + RB_PUT(pOpQ, pOp); + } + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + //--> clean up interal data structure<--// + _stp_psm_set_state(stp_psm, ACT); + + psm_fifo_lock(stp_psm); + osal_fifo_reset(&stp_psm->hold_fifo); + psm_fifo_unlock(stp_psm); + + //--> stop psm thread wait <--// + stp_psm->flag |= STP_PSM_RESET_EN; + osal_trigger_event(&stp_psm->wait_wmt_q); + + osal_unlock_sleepable_lock(&stp_psm->user_lock); + + STP_PSM_DBG_FUNC("PSM MODE RESET<============================\n\r"); + + return STP_PSM_OPERATION_SUCCESS; +} + +static INT32 _stp_psm_wait_wmt_event(void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData; + + STP_PSM_DBG_FUNC("%s, stp_psm->flag=0x%08x\n", __func__, stp_psm->flag); + + return ((stp_psm->flag & STP_PSM_WMT_EVENT_SLEEP_EN) || + (stp_psm->flag & STP_PSM_WMT_EVENT_WAKEUP_EN) || + (stp_psm->flag & STP_PSM_WMT_EVENT_ROLL_BACK_EN) || + (stp_psm->flag & STP_PSM_RESET_EN)); +} + + +static inline INT32 _stp_psm_wait_wmt_event_wq(MTKSTP_PSM_T *stp_psm){ + + INT32 retval = 0; + + if(stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + osal_wait_for_event_timeout(&stp_psm->wait_wmt_q, + _stp_psm_wait_wmt_event, + (void *)stp_psm); + + if(stp_psm->flag & STP_PSM_WMT_EVENT_WAKEUP_EN) + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_WAKEUP_EN; +// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); + //STP send data here: STP enqueue data to psm buffer. + _stp_psm_release_data(stp_psm); + //STP send data here: STP enqueue data to psm buffer. We release packet by the next one. + stp_psm->flag &= ~STP_PSM_BLOCK_DATA_EN; + //STP send data here: STP sends data directly without PSM. + _stp_psm_set_state(stp_psm, ACT); +// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); + + if (stp_psm_is_quick_ps_support()) + stp_psm_notify_wmt_sleep(stp_psm); + else + _stp_psm_start_monitor(stp_psm); + } + else if ( stp_psm->flag & STP_PSM_WMT_EVENT_SLEEP_EN) + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN; + _stp_psm_set_state(stp_psm, INACT); + + STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle++\n"); + mt_combo_plt_enter_deep_idle(COMBO_IF_UART); + STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle--\n"); + + STP_PSM_DBG_FUNC("sleep-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("sleep-wake_lock#(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + } + else if ( stp_psm->flag & STP_PSM_WMT_EVENT_ROLL_BACK_EN) + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; + if(_stp_psm_get_state(stp_psm) == ACT_INACT){ +// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); + _stp_psm_release_data(stp_psm); + stp_psm->flag &= ~STP_PSM_BLOCK_DATA_EN; + _stp_psm_set_state(stp_psm, ACT); +// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); + } else if(_stp_psm_get_state(stp_psm) == INACT_ACT) { + _stp_psm_set_state(stp_psm, INACT); + STP_PSM_INFO_FUNC("[WARNING]PSM state rollback due too wakeup fail\n"); + } + } + else if (stp_psm->flag & STP_PSM_RESET_EN) + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; + } + else + { + STP_PSM_ERR_FUNC("flag = %x<== Abnormal flag be set!!\n\r", stp_psm->flag); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + retval = STP_PSM_OPERATION_SUCCESS; + } + return retval; +} + +static inline INT32 _stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action){ + + INT32 retval = 0; + + if(action == EIRQ) + { + STP_PSM_DBG_FUNC("Call _stp_psm_notify_wmt_host_awake_wq\n\r"); + + _stp_psm_notify_wmt_host_awake_wq(stp_psm); + + return STP_PSM_OPERATION_FAIL; + } + + if((_stp_psm_get_state(stp_psm) < STP_PSM_MAX_STATE) && (_stp_psm_get_state(stp_psm) >= 0)) + { + STP_PSM_DBG_FUNC("state = %s, action=%s \n\r", g_psm_state[_stp_psm_get_state(stp_psm)], g_psm_action[action]); + } + + // If STP trigger WAKEUP and SLEEP, to do the job below + switch(_stp_psm_get_state(stp_psm)) + { + //stp trigger + case ACT_INACT: + + if(action == SLEEP) + { + STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, ready to INACT\n\r", g_psm_action[action]); + stp_psm->flag &= ~STP_PSM_WMT_EVENT_WAKEUP_EN; + stp_psm->flag |= STP_PSM_WMT_EVENT_SLEEP_EN; + + //wake_up(&stp_psm->wait_wmt_q); + osal_trigger_event(&stp_psm->wait_wmt_q); + } + else if(action == ROLL_BACK) + { + STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, back to ACT\n\r", g_psm_action[action]); + //stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; + stp_psm->flag |= STP_PSM_WMT_EVENT_ROLL_BACK_EN; + //wake_up(&stp_psm->wait_wmt_q); + osal_trigger_event(&stp_psm->wait_wmt_q); + } + else + { + if(action < STP_PSM_MAX_ACTION) + { + STP_PSM_ERR_FUNC("Action = %s, ACT_INACT state, the case should not happens\n\r", g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + else + { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + retval = STP_PSM_OPERATION_FAIL; + } + break; + //stp trigger + + case INACT_ACT: + + if(action == WAKEUP) + { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); + stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN; + stp_psm->flag |= STP_PSM_WMT_EVENT_WAKEUP_EN; + //wake_up(&stp_psm->wait_wmt_q); + osal_trigger_event(&stp_psm->wait_wmt_q); + } + else if(action == HOST_AWAKE) + { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); + stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN; + stp_psm->flag |= STP_PSM_WMT_EVENT_WAKEUP_EN; + //wake_up(&stp_psm->wait_wmt_q); + osal_trigger_event(&stp_psm->wait_wmt_q); + } + else if(action == ROLL_BACK) + { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, back to INACT\n\r", g_psm_action[action]); + // stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; + stp_psm->flag |= STP_PSM_WMT_EVENT_ROLL_BACK_EN; + //wake_up(&stp_psm->wait_wmt_q); + osal_trigger_event(&stp_psm->wait_wmt_q); + } + else + { + if(action < STP_PSM_MAX_ACTION) + { + STP_PSM_ERR_FUNC("Action = %s, INACT_ACT state, the case should not happens\n\r", g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + else + { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + retval = STP_PSM_OPERATION_FAIL; + } + break; + + case INACT: + + if(action < STP_PSM_MAX_ACTION) + { + STP_PSM_ERR_FUNC("Action = %s, INACT state, the case should not happens\n\r", g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + else + { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + + retval = -1; + + break; + + case ACT: + + if(action < STP_PSM_MAX_ACTION) + { + STP_PSM_ERR_FUNC("Action = %s, ACT state, the case should not happens\n\r", g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + else + { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + + retval = STP_PSM_OPERATION_FAIL; + + break; + + default: + + /*invalid*/ + if(action < STP_PSM_MAX_ACTION) + { + STP_PSM_ERR_FUNC("Action = %s, Invalid state, the case should not happens\n\r", g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + } + else + { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + + retval = STP_PSM_OPERATION_FAIL; + + break; + } + + return retval; + +} + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + INT32 ret = 0; + + if (stp_psm == NULL) + { + return STP_PSM_OPERATION_FAIL; + } + + switch(_stp_psm_get_state(stp_psm)) + { + case ACT: + + if(action == SLEEP) + { + if (stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR) { + STP_PSM_ERR_FUNC("psm monitor disabled, can't do sleep op\n"); + return STP_PSM_OPERATION_FAIL; + } + + _stp_psm_set_state(stp_psm, ACT_INACT); + + _stp_psm_release_data(stp_psm); + + if(stp_psm->wmt_notify) + { + stp_psm->wmt_notify(SLEEP); + _stp_psm_wait_wmt_event_wq(stp_psm); + } + else + { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } + else if(action == WAKEUP || action == HOST_AWAKE) + { + STP_PSM_INFO_FUNC("In ACT state, dont do WAKEUP/HOST_AWAKE again\n"); + _stp_psm_release_data(stp_psm); + } + else + { + STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + + ret = STP_PSM_OPERATION_FAIL; + + } + + break; + + case INACT: + + if(action == WAKEUP) + { + _stp_psm_set_state(stp_psm, INACT_ACT); + + if(stp_psm->wmt_notify) + { + STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); + mt_combo_plt_exit_deep_idle(COMBO_IF_UART); + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); + + stp_psm->wmt_notify(WAKEUP); + _stp_psm_wait_wmt_event_wq(stp_psm); + } + else + { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } + else if(action == HOST_AWAKE) + { + _stp_psm_set_state(stp_psm, INACT_ACT); + + if(stp_psm->wmt_notify) + { + STP_PSM_DBG_FUNC("host awake +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("host awake +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); + mt_combo_plt_exit_deep_idle(COMBO_IF_UART); + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); + + stp_psm->wmt_notify(HOST_AWAKE); + _stp_psm_wait_wmt_event_wq(stp_psm); + } + else + { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } + else if(action == SLEEP) + { + STP_PSM_INFO_FUNC("In INACT state, dont do SLEEP again\n"); + } + else + { + STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + ret = STP_PSM_OPERATION_FAIL; + } + + break; + + default: + + /*invalid*/ + STP_PSM_ERR_FUNC("invalid state, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag); + ret = STP_PSM_OPERATION_FAIL; + + break; + } + return ret; +} + +static inline void _stp_psm_stp_is_idle(ULONG data) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)data; + + stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY; + stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY; + + if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR)!= 0) + { + STP_PSM_DBG_FUNC("STP-PSM DISABLE!\n"); + return ; + } + + STP_PSM_INFO_FUNC("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep); + _stp_psm_notify_wmt_sleep_wq(stp_psm); +} + +static inline INT32 _stp_psm_init_monitor(MTKSTP_PSM_T *stp_psm) +{ + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + + STP_PSM_INFO_FUNC("init monitor\n"); + + stp_psm->psm_timer.timeoutHandler = _stp_psm_stp_is_idle; + stp_psm->psm_timer.timeroutHandlerData = (UINT32)stp_psm; + osal_timer_create(&stp_psm->psm_timer); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_deinit_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + STP_PSM_INFO_FUNC("deinit monitor\n"); + + osal_timer_stop_sync(&stp_psm->psm_timer); + } + + return 0; +} + +static inline INT32 _stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) +{ + INT32 iRet = -1; + +// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); + + if(stp_psm->flag & STP_PSM_BLOCK_DATA_EN) + { + iRet = 1; + } + else + { + iRet = 0; + } +// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); + return iRet; +} + +static inline INT32 _stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) +{ + if(stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR) + { + return 1; + } + else + { + return 0; + } +} + +static inline INT32 _stp_psm_do_wait(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state){ + + #define POLL_WAIT 20//200 + #define POLL_WAIT_TIME 2000 + + INT32 i = 0; + INT32 limit = POLL_WAIT_TIME/POLL_WAIT; + + while(_stp_psm_get_state(stp_psm)!=state && i < limit) + { + osal_msleep(POLL_WAIT); + i++; + STP_PSM_INFO_FUNC("STP is waiting state for %s, i=%d, state = %d\n", g_psm_state[state],i , _stp_psm_get_state(stp_psm)); + } + + if(i == limit) + { + STP_PSM_WARN_FUNC("-Wait for %s takes %d msec\n", g_psm_state[state], i*POLL_WAIT); + return STP_PSM_OPERATION_FAIL; + } + else + { + STP_PSM_DBG_FUNC("+Total waits for %s takes %d msec\n", g_psm_state[state], i*POLL_WAIT); + return STP_PSM_OPERATION_SUCCESS; + } +} + +static inline INT32 _stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) +{ + + INT32 ret = 0; + INT32 retry = 10; + P_OSAL_OP_Q pOpQ; + P_OSAL_OP pOp; + + STP_PSM_LOUD_FUNC("*** Do Force Wakeup!***\n\r"); + + //<1>If timer is active, we will stop it. + _stp_psm_stop_monitor(stp_psm); + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + pOpQ = &stp_psm->rFreeOpQ; + + while (!RB_EMPTY(&stp_psm->rActiveOpQ)) + { + RB_GET(&stp_psm->rActiveOpQ, pOp); + if (NULL != pOp && !RB_FULL(pOpQ)) + { + STP_PSM_DBG_FUNC("opid = %d\n", pOp->op.opId); + RB_PUT(pOpQ, pOp); + } + else + { + STP_PSM_ERR_FUNC("clear up active queue fail, freeQ full\n"); + } + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + //<5>We issue wakeup request into op queue. and wait for active. + do{ + ret = _stp_psm_notify_wmt_wakeup_wq(stp_psm); + + if(ret == STP_PSM_OPERATION_SUCCESS) + { + ret = _stp_psm_do_wait(stp_psm, ACT); + + //STP_PSM_INFO_FUNC("<< wait ret = %d, num of activeQ = %d\n", ret, RB_COUNT(&stp_psm->rActiveOpQ)); + if(ret == STP_PSM_OPERATION_SUCCESS) + { + break; + } + } + else + { + STP_PSM_ERR_FUNC("_stp_psm_notify_wmt_wakeup_wq fail!!\n"); + } + + //STP_PSM_INFO_FUNC("retry = %d\n", retry); + retry--; + + if(retry == 0) + { + break; + } + } + while(1); + + if(retry == 0) + { + return STP_PSM_OPERATION_FAIL; + } + else + { + return STP_PSM_OPERATION_SUCCESS; + } +} + +static inline INT32 _stp_psm_disable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = STP_PSM_OPERATION_FAIL; + + STP_PSM_DBG_FUNC("PSM Disable start\n\r"); + + ret = osal_lock_sleepable_lock(&stp_psm->user_lock); + if (ret) { + STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + + stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR; + ret = _stp_psm_do_wakeup(stp_psm); + osal_unlock_sleepable_lock(&stp_psm->user_lock); + if (ret == STP_PSM_OPERATION_SUCCESS) + { + STP_PSM_DBG_FUNC("PSM Disable Success\n"); + } + else + { + STP_PSM_ERR_FUNC("***PSM Disable Fail***\n"); + } + + return ret; +} + +static inline INT32 _stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) +{ + INT32 ret = STP_PSM_OPERATION_FAIL; + STP_PSM_LOUD_FUNC("PSM Enable start\n\r"); + + ret = osal_lock_sleepable_lock(&stp_psm->user_lock); + if (ret) { + STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + + stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR; + + ret = _stp_psm_do_wakeup(stp_psm); + if(ret == STP_PSM_OPERATION_SUCCESS) + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR; + stp_psm->idle_time_to_sleep = idle_time_to_sleep; + + if(osal_wake_lock_count(&stp_psm->wake_lock) == 0) + { + STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); + } + + _stp_psm_start_monitor(stp_psm); + + STP_PSM_DBG_FUNC("PSM Enable succeed\n\r"); + } + else + { + STP_PSM_ERR_FUNC("***PSM Enable Fail***\n"); + } + osal_unlock_sleepable_lock(&stp_psm->user_lock); + + return ret; +} + +INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) +{ + return osal_lock_sleepable_lock(&stp_psm->stp_psm_lock); +} + +INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) +{ + osal_unlock_sleepable_lock(&stp_psm->stp_psm_lock); + return 0; +} + +MTK_WCN_BOOL _stp_psm_is_quick_ps_support (VOID) +{ + if (stp_psm->is_wmt_quick_ps_support) + { + return (*(stp_psm->is_wmt_quick_ps_support))(); + } + STP_PSM_DBG_FUNC("stp_psm->is_wmt_quick_ps_support is NULL, return false\n\r"); + return MTK_WCN_BOOL_FALSE; +} + + +MTK_WCN_BOOL stp_psm_is_quick_ps_support (VOID) +{ + return _stp_psm_is_quick_ps_support(); +} + +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir){ + + //easy the variable maintain beween stp tx, rx thread. + //so we create variable for tx, rx respectively. + + static INT32 tx_cnt = 0; + static INT32 rx_cnt = 0; + static INT32 is_tx_first = 1; + static INT32 is_rx_first = 1; + static ULONG tx_end_time = 0; + static ULONG rx_end_time = 0; + + // + //BT A2DP TX CNT = 220, RX CNT = 843 + //BT FTP Transferring TX CNT = 574, RX CNT = 2233 (1228~1588) + //BT FTP Receiving TX CNT = 204, RX CNT = 3301 (2072~2515) + //BT OPP Tx TX_CNT= 330, RX CNT = 1300~1800 + //BT OPP Rx TX_CNT= (109~157), RX CNT = 1681~2436 + if(dir == 0)//tx + { + tx_cnt++; + + if(((LONG)jiffies - (LONG)tx_end_time >= 0) || (is_tx_first)) + { + tx_end_time = jiffies + (3*HZ); + STP_PSM_INFO_FUNC("tx cnt = %d in the previous 3 sec\n", tx_cnt); + //if(tx_cnt > 400)//for high traffic , not to do sleep. + if (tx_cnt > 300) + { + stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY; + stp_psm_start_monitor(stp_psm); + } + else + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY; + } + tx_cnt = 0; + if(is_tx_first) + is_tx_first = 0; + } + } + else + { + rx_cnt++; + + if(((LONG)jiffies - (LONG)rx_end_time >= 0) || (is_rx_first)) + { + rx_end_time = jiffies + (3*HZ); + STP_PSM_INFO_FUNC("rx cnt = %d in the previous 3 sec\n", rx_cnt); + + //if(rx_cnt > 2000)//for high traffic , not to do sleep. + if(rx_cnt > 1200)//for high traffic , not to do sleep. + { + stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY; + stp_psm_start_monitor(stp_psm); + } + else + { + stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY; + } + rx_cnt = 0; + if(is_rx_first) + is_rx_first = 0; + } + } + + return 0; +} + +/*external function for WMT module to do sleep/wakeup*/ +INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) +{ + return _stp_psm_set_state(stp_psm, state); +} + + +INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_aquire(stp_psm); +} + + +INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_release(stp_psm); +} + + + +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_do_wakeup(stp_psm); +} + +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + + return _stp_psm_notify_stp(stp_psm, action); +} + +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_notify_wmt_wakeup_wq(stp_psm); +} + +INT32 stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm){ + + return _stp_psm_notify_wmt_sleep_wq(stp_psm); +} + +INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_start_monitor(stp_psm); +} + +INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_is_to_block_traffic(stp_psm); +} + +INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_is_disable(stp_psm); +} + +INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_has_pending_data(stp_psm); +} + +INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_release_data(stp_psm); +} + +INT32 +stp_psm_hold_data ( + MTKSTP_PSM_T *stp_psm, + const UINT8 *buffer, + const UINT32 len, + const UINT8 type + ) +{ + return _stp_psm_hold_data(stp_psm, buffer, len, type); +} + +INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_disable(stp_psm); +} + +INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) +{ + return _stp_psm_enable(stp_psm, idle_time_to_sleep); +} + +INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm) +{ + stp_psm_set_sleep_enable(stp_psm); + + return _stp_psm_reset(stp_psm); +} + +INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_notify_wmt_sleep_wq(stp_psm); +} + + +INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + stp_psm->sleep_en = 1; + STP_PSM_DBG_FUNC("\n"); + ret = 0; + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + + +INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + stp_psm->sleep_en = 0; + STP_PSM_DBG_FUNC("\n"); + ret = 0; + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + + +/* stp_psm_check_sleep_enable - to check if sleep cmd is enabled or not + * @ stp_psm - pointer of psm + * + * return 1 if sleep is enabled; else return 0 if disabled; else error code + */ +INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + ret = stp_psm->sleep_en; + STP_PSM_DBG_FUNC("%s \n", ret? "enabled" : "disabled"); + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + + +MTKSTP_PSM_T *stp_psm_init(void) +{ + INT32 err = 0; + INT32 i = 0; + INT32 ret = -1; + + STP_PSM_INFO_FUNC("psm init\n"); + + stp_psm->work_state = ACT; + stp_psm->wmt_notify = wmt_lib_ps_stp_cb; + stp_psm->is_wmt_quick_ps_support = wmt_lib_is_quick_ps_support; + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; + stp_psm->flag = 0; + stp_psm->stp_tx_cb = NULL; + stp_psm_set_sleep_enable(stp_psm); + + ret = osal_fifo_init(&stp_psm->hold_fifo, NULL, STP_PSM_FIFO_SIZE); + if(ret < 0) + { + STP_PSM_ERR_FUNC("FIFO INIT FAILS\n"); + goto ERR_EXIT4; + } + + osal_fifo_reset(&stp_psm->hold_fifo); + osal_sleepable_lock_init(&stp_psm->user_lock); + psm_fifo_lock_init(stp_psm); + osal_unsleepable_lock_init(&stp_psm->wq_spinlock); + osal_sleepable_lock_init(&stp_psm->stp_psm_lock); + +// osal_unsleepable_lock_init(&stp_psm->flagSpinlock); + + osal_memcpy(stp_psm->wake_lock.name, "MT662x", 6); + osal_wake_lock_init(&stp_psm->wake_lock); + + osal_event_init(&stp_psm->STPd_event); + RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); + RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); + /* Put all to free Q */ + for (i = 0; i < STP_OP_BUF_SIZE; i++) + { + osal_signal_init(&(stp_psm->arQue[i].signal)); + _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, &(stp_psm->arQue[i])); + } + //stp_psm->current_active_op = NULL; + stp_psm->last_active_opId = STP_OPID_PSM_INALID; + /*Generate BTM thread, to servie STP-CORE and WMT-CORE for sleeping, waking up and host awake*/ + stp_psm->PSMd.pThreadData = (VOID *)stp_psm; + stp_psm->PSMd.pThreadFunc = (VOID *)_stp_psm_proc; + osal_memcpy(stp_psm->PSMd.threadName, PSM_THREAD_NAME, osal_strlen(PSM_THREAD_NAME)); + + ret = osal_thread_create(&stp_psm->PSMd); + if (ret < 0) + { + STP_PSM_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT5; + } + + //init_waitqueue_head(&stp_psm->wait_wmt_q); + stp_psm->wait_wmt_q.timeoutValue = STP_PSM_WAIT_EVENT_TIMEOUT; + osal_event_init(&stp_psm->wait_wmt_q); + + err = _stp_psm_init_monitor(stp_psm); + if(err) + { + STP_PSM_ERR_FUNC("__stp_psm_init ERROR\n"); + goto ERR_EXIT6; + } + + //Start STPd thread + ret = osal_thread_run(&stp_psm->PSMd); + if(ret < 0) + { + STP_PSM_ERR_FUNC("osal_thread_run FAILS\n"); + goto ERR_EXIT6; + } + + //psm disable in default + _stp_psm_disable(stp_psm); + + + return stp_psm; + +ERR_EXIT6: + + ret = osal_thread_destroy(&stp_psm->PSMd); + if(ret < 0) + { + STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); + goto ERR_EXIT5; + } +ERR_EXIT5: + osal_fifo_deinit(&stp_psm->hold_fifo); +ERR_EXIT4: + + return NULL; +} + +INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = -1; + + STP_PSM_INFO_FUNC("psm deinit\n"); + + if(!stp_psm) + { + return STP_PSM_OPERATION_FAIL; + } + + ret = osal_thread_destroy(&stp_psm->PSMd); + if(ret < 0) + { + STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); + } + + ret = _stp_psm_deinit_monitor(stp_psm); + if(ret < 0) + { + STP_PSM_ERR_FUNC("_stp_psm_deinit_monitor ERROR\n"); + } + + osal_fifo_deinit(&stp_psm->hold_fifo); + osal_sleepable_lock_deinit(&stp_psm->user_lock); + psm_fifo_lock_deinit(stp_psm); + osal_unsleepable_lock_deinit(&stp_psm->wq_spinlock); + osal_sleepable_lock_deinit(&stp_psm->stp_psm_lock); +// osal_unsleepable_lock_deinit(&stp_psm->flagSpinlock); + + return STP_PSM_OPERATION_SUCCESS; +} + +EXPORT_SYMBOL(mtk_wcn_stp_psm_dbg_level); + diff --git a/drivers/mtk_wcn_combo/common/core/stp_core.c b/drivers/mtk_wcn_combo/common/core/stp_core.c new file mode 100755 index 000000000000..50dc66d97ce9 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/stp_core.c @@ -0,0 +1,3254 @@ + +#include "stp_core.h" +#include "psm_core.h" +#include "btm_core.h" +#include "stp_dbg.h" + +#define PFX "[STP] " +#define STP_LOG_DBG 4 +#define STP_LOG_PKHEAD 3 +#define STP_LOG_INFO 2 +#define STP_LOG_WARN 1 +#define STP_LOG_ERR 0 + +#define STP_DEL_SIZE 2 /* STP delimiter length */ + +UINT32 gStpDbgLvl = STP_LOG_INFO; + +#define REMOVE_USELESS_LOG 1 + + +/* global variables */ +static const UINT8 stp_delimiter[STP_DEL_SIZE] = {0x55, 0x55}; +static INT32 fgEnableNak = 0; // 0=enable NAK; 1=disable NAK +static INT32 fgEnableDelimiter = 0; // 0=disable Delimiter; 1=enable Delimiter + +/* common interface */ +static IF_TX sys_if_tx = NULL; +/* event/signal */ +static EVENT_SET sys_event_set = NULL; +static EVENT_TX_RESUME sys_event_tx_resume = NULL; +static FUNCTION_STATUS sys_check_function_status = NULL; +/* kernel lib */ +//INT32 g_block_tx = 0; +static mtkstp_context_struct stp_core_ctx = {0}; + +#define STP_PSM_CORE(x) ((x).psm) +#define STP_SET_PSM_CORE(x,v) ((x).psm = (v)) + +#define STP_BTM_CORE(x) ((x).btm) +#define STP_SET_BTM_CORE(x,v) ((x).btm = (v)) + +#define STP_IS_ENABLE(x) ((x).f_enable != 0) +#define STP_NOT_ENABLE(x) ((x).f_enable == 0) +#define STP_SET_ENABLE(x,v) ((x).f_enable = (v)) + +#define STP_IS_READY(x) ((x).f_ready != 0) +#define STP_NOT_READY(x) ((x).f_ready == 0) +#define STP_SET_READY(x,v) ((x).f_ready = (v)) + +#define STP_PENDING_TYPE(x) ((x).f_pending_type) +#define STP_SET_PENDING_TYPE(x,v) ((x).f_pending_type = (v)) + +#define STP_BLUE_ANGEL (0) +#define STP_BLUE_Z (1) +#define STP_BT_STK(x) ((x).f_bluez) +#define STP_BT_STK_IS_BLUEZ(x) ((x).f_bluez == (STP_BLUE_Z)) +#define STP_SET_BT_STK(x,v) ((x).f_bluez = (v)) + +#define STP_IS_ENABLE_DBG(x) ((x).f_dbg_en != 0) +#define STP_NOT_ENABLE_DBG(x) ((x).f_dbg_en == 0) +#define STP_SET_ENABLE_DBG(x,v) ((x).f_dbg_en = (v)) + +#define STP_IS_ENABLE_RST(x) ((x).f_autorst_en != 0) +#define STP_NOT_ENABLE_RST(x) ((x).f_autorst_en == 0) +#define STP_SET_ENABLE_RST(x,v) ((x).f_autorst_en = (v)) + +#define STP_SUPPORT_PROTOCOL(x) ((x).f_mode) +#define STP_SET_SUPPORT_PROTOCOL(x,v) ((x).f_mode = (v)) + +#define STP_FW_COREDUMP_FLAG(x) ((x).f_coredump) +#define STP_SET_FW_COREDUMP_FLAG(x,v) ((x).f_coredump = (v)) +#define STP_ENABLE_FW_COREDUMP(x,v) ((x).en_coredump = (v)) +#define STP_ENABLE_FW_COREDUMP_FLAG(x) ((x).en_coredump) + +#define STP_WMT_LAST_CLOSE(x) ((x).f_wmt_last_close) +#define STP_SET_WMT_LAST_CLOSE(x,v) ((x).f_wmt_last_close = (v)) + + +/*[PatchNeed]Need to calulate the timeout value*/ +static UINT32 mtkstp_tx_timeout = MTKSTP_TX_TIMEOUT; +static mtkstp_parser_state prev_state = -1; + + +#define CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +#ifdef CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +static MTKSTP_DBG_T *g_mtkstp_dbg = NULL; +#endif +static VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len); +static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc); +static VOID stp_update_tx_queue(UINT32 txseq); +static VOID stp_rest_ctx_state (VOID); +static VOID stp_change_rx_state(mtkstp_parser_state next); +static void stp_tx_timeout_handler(ULONG data); +static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len); +static VOID stp_dump_tx_queue(UINT32 txseq); +static INT32 stp_is_apply_powersaving(VOID); +static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type); +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length); +static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length); +static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type); +static VOID stp_send_tx_queue(UINT32 txseq); +static VOID stp_send_ack(UINT8 txAck, UINT8 nak); +INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type); +static INT32 stp_process_rxack(VOID); +static VOID stp_process_packet(VOID); +VOID stp_do_tx_timeout(VOID); + +/*Bad*/ +extern INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size); +#if WMT_PLAT_ALPS +extern void stop_log(void);//uart export API +#endif + +static INT32 stp_ctx_lock_init (mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + #if defined(CONFIG_PROVE_LOCKING) + osal_unsleepable_lock_init(&((pctx)->stp_mutex)); + return 0; + #else + return osal_unsleepable_lock_init(&((pctx)->stp_mutex)); + #endif +#else + #if defined(CONFIG_PROVE_LOCKING) + osal_sleepable_lock_init(&((pctx)->stp_mutex)); + return 0; + #else + return osal_sleepable_lock_init(&((pctx)->stp_mutex)); + #endif +#endif +} + +static INT32 stp_ctx_lock_deinit (mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_unsleepable_lock_deinit(&((pctx)->stp_mutex)); +#else + return osal_sleepable_lock_deinit(&((pctx)->stp_mutex)); +#endif +} + +static INT32 stp_ctx_lock (mtkstp_context_struct *pctx) +{ + //dump_stack(); + //printk("stp_lock\n\r"); +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_lock_unsleepable_lock(&((pctx)->stp_mutex)); +#else + return osal_lock_sleepable_lock(&((pctx)->stp_mutex)); +#endif +} + +static INT32 stp_ctx_unlock (mtkstp_context_struct *pctx) +{ + //dump_stack(); + //printk("stp_unlock\n\r"); + +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_unlock_unsleepable_lock(&((pctx)->stp_mutex)); +#else + return osal_unlock_sleepable_lock(&((pctx)->stp_mutex)); +#endif +} + + +MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel) +{ + if (0 <= dbglevel && dbglevel <= 4) + { + gStpDbgLvl = dbglevel; + STP_INFO_FUNC("gStpDbgLvl = %d\n", gStpDbgLvl); + return MTK_WCN_BOOL_TRUE; + } + else + { + STP_INFO_FUNC("invalid stp debug level. gStpDbgLvl = %d\n", gStpDbgLvl); + } + return MTK_WCN_BOOL_FALSE; +} +#if 0 +/***************************************************************************** +* FUNCTION +* crc16 +* DESCRIPTION +* Compute the CRC-16 for the data buffer +* PARAMETERS +* crc [IN] previous CRC value +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* the updated CRC value +*****************************************************************************/ +static UINT16 crc16(const UINT8 *buffer, const UINT32 length) +{ + UINT32 crc, i; + + //FIXME: Add STP checksum feature + crc = 0; + for (i = 0; i < length; i++, buffer++) + { + crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; + } + return crc; +} + +#endif + + +VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len){ + +#ifndef CONFIG_LOG_STP_INTERNAL + return ; +#endif + + if(STP_IS_ENABLE_DBG(stp_core_ctx)){ + stp_dbg_log_pkt(g_mtkstp_dbg, + STP_DBG_PKT, + type, //type + txAck, //ack + seq, //seq + crc, //crc + dir, //dir + len, //len + pBuf); //body + } + else + { + STP_DBG_FUNC("stp_dbg not enabled"); + } +} + +/***************************************************************************** +* FUNCTION +* stp_check_crc +* DESCRIPTION +* check the check sum of packet payload +* PARAMETERS +* pdata [IN] the data want to check +* length [IN] the length of pdata +* crc [IN] the crc of pdata +* RETURNS +* KAL_TRUE crc is ok +* KAL_FALSE crc is wrong +*****************************************************************************/ +static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + UINT16 checksum; + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + + // FIXME: Add STP feature: check or skip crc + + checksum = osal_crc16(buffer, length); + if (checksum == crc) + { + return MTK_WCN_BOOL_TRUE; + } + else + { + STP_ERR_FUNC("CRC fail, length = %d, rx = %x, calc = %x \r\n", length, crc, checksum); + return MTK_WCN_BOOL_FALSE; + } +} + +/***************************************************************************** +* FUNCTION +* stp_update_tx_queue +* DESCRIPTION +* update packet's ACK field +* PARAMETERS +* txseq [IN] index of the tx packet which we want to update +* RETURNS +* void +*****************************************************************************/ +static void stp_update_tx_queue(UINT32 txseq) +{ + INT32 tx_read, i; + UINT8 checksum = 0; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + stp_core_ctx.tx_buf[tx_read] &= 0xf8; + stp_core_ctx.tx_buf[tx_read] |= stp_core_ctx.sequence.txack; + + for (i = 0; i < 3; i++) + { + checksum += stp_core_ctx.tx_buf[tx_read]; + tx_read++; + if( tx_read >= MTKSTP_BUFFER_SIZE) + { + tx_read -= MTKSTP_BUFFER_SIZE; + } + } + + stp_core_ctx.tx_buf[tx_read] = checksum; + + return; +} + +/***************************************************************************** +* FUNCTION +* stp_rest_ctx_state +* DESCRIPTION +* Reset stp context state variables only. Mutex and timer resources are not touched. +* +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_rest_ctx_state (VOID) +{ + INT32 i; + + stp_ctx_lock(&stp_core_ctx); + stp_core_ctx.rx_counter = 0; + + /*reset rx buffer pointer*/ + for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) + { + stp_core_ctx.ring[i].read_p = 0; + stp_core_ctx.ring[i].write_p = 0; + } + + /*reset tx buffer pointer*/ + stp_core_ctx.tx_write = 0; + stp_core_ctx.tx_read = 0; + + /*reset STP protocol context*/ + stp_core_ctx.parser.state = MTKSTP_SYNC; + stp_core_ctx.sequence.txseq = 0; + stp_core_ctx.sequence.txack = 7; + stp_core_ctx.sequence.rxack = 7; + stp_core_ctx.sequence.winspace = MTKSTP_WINSIZE; + stp_core_ctx.sequence.expected_rxseq = 0; + stp_core_ctx.sequence.retry_times = 0; + stp_core_ctx.inband_rst_set = 0; + + stp_ctx_unlock(&stp_core_ctx); +} + +/***************************************************************************** +* FUNCTION +* stp_change_rx_state +* DESCRIPTION +* change the rx fsm of STP to "next" +* PARAMETERS +* next [IN] the next state of rx fsm +* RETURNS +* void +*****************************************************************************/ +static VOID stp_change_rx_state(mtkstp_parser_state next) +{ + prev_state = stp_core_ctx.parser.state; + stp_core_ctx.parser.state = next; + + return; +} + +//static void stp_tx_timeout_handler(void){ +static void stp_tx_timeout_handler(ULONG data) +{ + STP_WARN_FUNC("call retry btm retry wq ...\n"); + /*shorten the softirq lattency*/ + #if WMT_PLAT_ALPS + stop_log(); + #endif + stp_btm_notify_stp_retry_wq(STP_BTM_CORE(stp_core_ctx)); + STP_WARN_FUNC("call retry btm retry wq ...#\n"); +} + +VOID stp_do_tx_timeout(VOID) +{ + UINT32 seq; + UINT32 ret; + UINT8 resync[4]; + + STP_WARN_FUNC("==============================================================================\n"); + + stp_ctx_lock(&stp_core_ctx); + + seq = stp_core_ctx.sequence.rxack; + INDEX_INC(seq); + + if (seq != stp_core_ctx.sequence.txseq) + { + osal_memset(&resync[0], 127, 4); + (*sys_if_tx)(&resync[0], 4, &ret); + if (ret != 4) + { + STP_ERR_FUNC("mtkstp_tx_timeout_handler: send resync fail\n"); + osal_assert(0); + } + + + do + { + STP_WARN_FUNC("[stp.ctx]*rxack (=last rx ack) = %d\n\r", stp_core_ctx.sequence.rxack); + STP_WARN_FUNC("[stp.ctx]txack (=last rx seq)= %d\n\r", stp_core_ctx.sequence.txack); + STP_WARN_FUNC("[stp.ctx]*txseq (=next tx seq)= %d\n\r", stp_core_ctx.sequence.txseq); + STP_WARN_FUNC("Resend STP packet from %d -> %d\n\r", seq , + (stp_core_ctx.sequence.txseq <= 0)?(7):(stp_core_ctx.sequence.txseq - 1)); + stp_dump_tx_queue(seq); + + stp_send_tx_queue(seq); + INDEX_INC(seq); + } while (seq != stp_core_ctx.sequence.txseq); + + } + + osal_timer_stop(&stp_core_ctx.tx_timer); + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + + if (stp_core_ctx.sequence.winspace == MTKSTP_WINSIZE) + { + osal_timer_stop(&stp_core_ctx.tx_timer); + STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); + } + else + { + stp_core_ctx.sequence.retry_times++; + STP_ERR_FUNC("mtkstp_tx_timeout_handler, retry = %d\n", stp_core_ctx.sequence.retry_times); + + /*If retry too much, try to recover STP by return back to initializatin state*/ + /*And not to retry again*/ + if (stp_core_ctx.sequence.retry_times > MTKSTP_RETRY_LIMIT) + { + osal_timer_stop(&stp_core_ctx.tx_timer); + STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); + + STP_ERR_FUNC("TX retry limit = %d\n", MTKSTP_RETRY_LIMIT); + osal_assert(0); + // stop_log(); + mtk_wcn_stp_dbg_dump_package(); + stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx)); + + /*Whole Chip Reset Procedure Invoke*/ + /*if(STP_NOT_ENABLE_DBG(stp_core_ctx))*/ + { + osal_dbg_assert_aee("[MT662x]NoAck", "**STP Tx Timeout**\n F/W has NO any RESPONSE. Please check F/W status first\n"); + if(STP_IS_ENABLE_RST(stp_core_ctx)) + { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } + else + { + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + } + } + + stp_ctx_unlock(&stp_core_ctx); + STP_WARN_FUNC("==============================================================================#\n"); + return; +} + +static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len) +{ + osal_buffer_dump(buf, title, len, 32); +} + +/***************************************************************************** + * FUNCTION + * stp_tx_timeout_handler + * DESCRIPTION + * tx timeout handler, send resync & retransmitt + * PARAMETERS + * void + * RETURNS + * void + *****************************************************************************/ +static VOID stp_dump_tx_queue(UINT32 txseq) +{ + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + STP_ERR_FUNC("tx_seq=%d ..", txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) + { + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q", (tx_length >= 8)?(8):(tx_length)); + } + else + { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q_0", (last_len >= 8) ? (8):(last_len)); + stp_dump_data(&stp_core_ctx.tx_buf[0], "tx_q_0", ((tx_length - last_len)?(8):(tx_length - last_len))); + } +} + +/***************************************************************************** +* FUNCTION +* stp_is_apply_powersaving +* DESCRIPTION +* Check if STP support power saving mode. +* PARAMETERS +* +* RETURNS +* True: support power saving False: not support power saving +*****************************************************************************/ +static INT32 stp_is_apply_powersaving(VOID){ + + if(STP_IS_READY(stp_core_ctx) && !stp_psm_is_disable(STP_PSM_CORE(stp_core_ctx))) + { + //osal_dbg_print("apply power saving\n"); + return MTK_WCN_BOOL_TRUE; + } + else + { + if (mtk_wcn_stp_is_sdio_mode()) return MTK_WCN_BOOL_FALSE; + + STP_DBG_FUNC("not apply power saving\n"); + return MTK_WCN_BOOL_FALSE; + } +} +/***************************************************************************** +* FUNCTION +* stp_is_privileges_cmd +* DESCRIPTION +* Check if the data is privilege command +* PARAMETERS +* +* RETURNS +* True/False +*****************************************************************************/ +static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type) +{ + typedef struct privileges_cmd { + UINT32 length; + UINT8 type; + UINT8 buf[7]; // MAX length of target command is only 5 currently + } p_cmd_t; + + p_cmd_t p_cmd_table[] = { + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x01}}, // sleep command + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x02}}, // host_awake command + }; + + UINT32 i; + UINT32 size = sizeof(p_cmd_table)/sizeof(p_cmd_table[0]); + + for (i = 0; i < size; i++) + { + if (type != p_cmd_table[i].type) + { + continue; + } + + if (length != p_cmd_table[i].length) + { + continue; + } + + if (osal_memcmp(p_cmd_table[i].buf, buffer, length)) + { + continue; + } + + // matched entry is found + STP_DBG_FUNC("It's p_cmd_t\n"); + return MTK_WCN_BOOL_TRUE; + } + + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* tx_queue_room_available +* DESCRIPTION +* check room if availabe, +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length) +{ + UINT32 roomLeft; + + /* + Get availale space of TX Queue + */ + if (stp_core_ctx.tx_read <= stp_core_ctx.tx_write) + { + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write + stp_core_ctx.tx_read - 1; + } + else + { + roomLeft = stp_core_ctx.tx_read - stp_core_ctx.tx_write - 1; + } + + if (roomLeft < length) + { + STP_ERR_FUNC("%s: tx queue room shortage\n", __FUNCTION__); + return MTK_WCN_BOOL_FALSE; + } + else + { + return MTK_WCN_BOOL_TRUE; + }; +} + +/***************************************************************************** +* FUNCTION +* stp_add_to_tx_queue +* DESCRIPTION +* put data to tx queue +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length) +{ + UINT32 last_len; + + // Get availale space of TX Queue + if (length + stp_core_ctx.tx_write < MTKSTP_BUFFER_SIZE) + { + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, length); + stp_core_ctx.tx_write += length; + } + else + { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write; + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, last_len); + osal_memcpy(stp_core_ctx.tx_buf, buffer + last_len, length - last_len); + + stp_core_ctx.tx_write = length - last_len; + } + + return; +} + +/***************************************************************************** +* FUNCTION +* stp_add_to_rx_queue +* DESCRIPTION +* put data to corresponding task's rx queue and notify corresponding task +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] corresponding task index +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type) +{ + UINT32 roomLeft, last_len; + + stp_ctx_lock(&stp_core_ctx); + + if (stp_core_ctx.ring[type].read_p <= stp_core_ctx.ring[type].write_p) + { + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p + stp_core_ctx.ring[type].read_p - 1; + } + else + { + roomLeft = stp_core_ctx.ring[type].read_p - stp_core_ctx.ring[type].write_p - 1; + } + + if (roomLeft < length) + { + stp_ctx_unlock(&stp_core_ctx); + STP_ERR_FUNC("Queue is full !!!, type = %d\n", type); + osal_assert(0); + return (-1); + } + + if (length + stp_core_ctx.ring[type].write_p < MTKSTP_BUFFER_SIZE) + { + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, length); + stp_core_ctx.ring[type].write_p += length; + } + else + { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p; + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, last_len); + osal_memcpy(stp_core_ctx.ring[type].buffer, buffer + last_len, length - last_len); + stp_core_ctx.ring[type].write_p = length - last_len; + } + + stp_ctx_unlock(&stp_core_ctx); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* stp_send_tx_queue +* DESCRIPTION +* send data in tx buffer to common interface +* PARAMETERS +* txseq [IN] sequence number of outgoing packet in tx buffer +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_tx_queue(UINT32 txseq) +{ + UINT32 ret; + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + stp_update_tx_queue(txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) + { + + (*sys_if_tx)(&stp_core_ctx.tx_buf[tx_read], tx_length, &ret); + + if (ret != tx_length) + { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length, ret); + osal_assert(0); + } + } + else + { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + (*sys_if_tx)(&stp_core_ctx.tx_buf[tx_read], last_len, &ret); + + if (ret != last_len) + { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", last_len, ret); + osal_assert(0); + } + + (*sys_if_tx)(&stp_core_ctx.tx_buf[0], tx_length - last_len, &ret); + + if (ret != tx_length - last_len) + { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length - last_len, ret); + osal_assert(0); + } + } + + return; +} + + +/***************************************************************************** +* FUNCTION +* stp_send_ack +* DESCRIPTION +* send ack packet to the peer +* PARAMETERS +* txAck [IN] Ack number +* nak [IN] 0 = ack; !0 = NAK +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_ack(UINT8 txAck, UINT8 nak) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE]; + UINT32 ret; + INT32 iStatus; + + mtkstp_header[0] = 0x80 + (0 << 3) + txAck;//stp_core_ctx.sequence.txack; + + if (fgEnableNak == 0) + { + mtkstp_header[1] = 0x00; // disable NAK + } + else + { + mtkstp_header[1] = ((nak == 0) ? 0x00 : 0x80); + } + + mtkstp_header[2] = 0; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + + stp_dbg_pkt_log(STP_TASK_INDX, + txAck, + 0, + 0, + PKT_DIR_TX, + NULL, + 0); + + if(fgEnableDelimiter == 1) + { + iStatus = (*sys_if_tx)(&stp_delimiter[0], STP_DEL_SIZE, &ret); + STP_DUMP_PACKET_HEAD((PUINT8)&stp_delimiter[0], "tx del", STP_DEL_SIZE); + if (ret != STP_DEL_SIZE) + { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", STP_DEL_SIZE, ret, iStatus); + osal_assert(0); + } + } + + iStatus = (*sys_if_tx)(&mtkstp_header[0], MTKSTP_HEADER_SIZE, &ret); + + if (ret != MTKSTP_HEADER_SIZE) + { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", MTKSTP_HEADER_SIZE, ret, iStatus); + osal_assert(0); + } + + return; +} + + + +INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + UINT8 *p_tx_buf = NULL; + UINT16 crc; + INT32 ret = 0; + + stp_ctx_lock(&stp_core_ctx); + + /*Only WMT can set raw data */ + if(STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) + { + //no op + } + else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) + { + //ret = mtk_wcn_stp_send_data_raw(buffer, length, type); + } + + // STP over SDIO + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) + { + osal_printtimeofday("[ STP][SDIO][ B][W]"); + + mtkstp_header[0] = 0x80; + mtkstp_header[1] = (type << 4) + (((length)>>8) & 0x0f); + mtkstp_header[2] = (length) & 0xff; + mtkstp_header[3] = 0x00; + + p_tx_buf = &stp_core_ctx.tx_buf[0]; + osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); + p_tx_buf += MTKSTP_HEADER_SIZE; + + osal_memcpy(p_tx_buf, buffer, length); + p_tx_buf += length; + + temp[0] = 0x00; + temp[1] = 0x00; + osal_memcpy(p_tx_buf, temp, 2); + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, + 0, + PKT_DIR_TX, + buffer, + length); + (*sys_if_tx)(&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE+length+2), &ret); + if ( (MTKSTP_HEADER_SIZE+length+2) != ret ) + { + STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); + osal_assert(0); + ret = 0; + } + else + { + ret = (INT32)length; + } + + osal_printtimeofday("[ STP][SDIO][ E][W]"); + } + + // STP over UART + else if ( mtk_wcn_stp_is_uart_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) + { + + if ((stp_core_ctx.sequence.winspace > 0) && + (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) + { + mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; + mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); + mtkstp_header[2] = length & 0xff; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + + stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; + + if (fgEnableDelimiter == 1) + { + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; + stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); + } + + stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); + + /*Make Payload*/ + stp_add_to_tx_queue(buffer, length); + + /*Make CRC*/ + crc = osal_crc16(buffer, length); + temp[0] = crc & 0xff; + temp[1] = (crc & 0xff00) >> 8; + stp_add_to_tx_queue(temp, 2); + + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, + crc, + PKT_DIR_TX, + buffer, + length); + + /*Kick to UART*/ + stp_send_tx_queue(stp_core_ctx.sequence.txseq); + INDEX_INC(stp_core_ctx.sequence.txseq); + stp_core_ctx.sequence.winspace--; + + /*Setup the Retry Timer*/ + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + { + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + } + else + { + STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); + } + ret = (INT32)length; + } + else + { + /* No winspace to send. Let caller retry*/ + STP_ERR_FUNC("%s: There is no winspace/txqueue to send !!!\n", __FUNCTION__); + ret = 0; + } + } + + stp_ctx_unlock(&stp_core_ctx); + + return ret; +} + +/***************************************************************************** +* FUNCTION +* stp_process_rxack +* DESCRIPTION +* process ack packet +* PARAMETERS +* void +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 stp_process_rxack(VOID) +{ + INT32 j, k; + UINT8 rxack; + INT32 fgResult = (-1); + if (stp_core_ctx.sequence.rxack != stp_core_ctx.parser.ack) + { + j = k = 0; + rxack = stp_core_ctx.sequence.rxack; + INDEX_INC(rxack); + while (rxack != stp_core_ctx.sequence.txseq) + { + j++; + if (rxack == stp_core_ctx.parser.ack) + { + k = 1; + break; + } + INDEX_INC(rxack); + } + if (k == 1) + { + stp_core_ctx.sequence.rxack = stp_core_ctx.parser.ack; + stp_core_ctx.tx_read = stp_core_ctx.tx_start_addr[rxack] + stp_core_ctx.tx_length[rxack]; + if (stp_core_ctx.tx_read >= MTKSTP_BUFFER_SIZE) + { + stp_core_ctx.tx_read -= MTKSTP_BUFFER_SIZE; + } + stp_core_ctx.sequence.winspace += j; + stp_core_ctx.sequence.retry_times = 0; + + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + { + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + } + fgResult = 0; + } + } + + return fgResult; +} + +/***************************************************************************** +* FUNCTION +* stp_process_packet +* DESCRIPTION +* process STP packet +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_process_packet(VOID) +{ + INT32 fgTriggerResume = (-1); + UINT8 txAck = 0; + static INT32 fgRxOk = 0; + MTK_WCN_BOOL b; + MTK_WCN_BOOL is_function_active = 0; + static INT32 stp_process_packet_fail_count = 0; + + stp_dbg_pkt_log(stp_core_ctx.parser.type, + stp_core_ctx.parser.ack, + stp_core_ctx.parser.seq, + stp_core_ctx.parser.crc, + PKT_DIR_RX, + stp_core_ctx.rx_buf, + stp_core_ctx.parser.length); + /*Optimization*/ + /*If bluez, direct send packet to hci_core not through RX buffer!*/ + if((stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) && + (stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) + { + /*Indicate packet to hci_stp*/ + STP_DBG_FUNC("Send Packet to BT_SUBFUCTION, len = %d\n", stp_core_ctx.rx_counter); + + b=mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if(b) + { + STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); + } + + stp_ctx_lock(&stp_core_ctx); + + /*Process rx ack*/ + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + txAck = stp_core_ctx.sequence.txack; + + /*Send ack back*/ + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); + + fgRxOk = 0; + } + /* sequence matches expected, enqueue packet*/ + else if (stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) + { + is_function_active = ((*sys_check_function_status)(stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) == STATUS_FUNCTION_ACTIVE); + /*If type is valid and function works, then try to enqueue*/ + if ((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) && (is_function_active == MTK_WCN_BOOL_TRUE)) + { + if(stp_core_ctx.parser.type == BT_TASK_INDX) + { + const static UINT8 rst_buf[7] = {0x04, 0x0e, 0x04, 0x01, 0x3, 0xc,0x00}; + if(!osal_strncmp(stp_core_ctx.rx_buf, rst_buf, 7)) + { + osal_printtimeofday("############ BT Rest end <--"); + } + } + + + + fgRxOk = stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, stp_core_ctx.parser.type); + } + else + { + if(is_function_active == MTK_WCN_BOOL_FALSE) + { + STP_ERR_FUNC("function type = %d is inactive, so no en-queue to rx\n", stp_core_ctx.parser.type); + fgRxOk = 0;/*drop packet*/ + } + else + { + STP_ERR_FUNC("mtkstp_process_packet: type = %x, the type is invalid\n", stp_core_ctx.parser.type); + fgRxOk = 0;/*drop packet*/ + } + } + + /* enqueue successfully */ + if(fgRxOk == 0) + { + stp_process_packet_fail_count = 0; + /*notify corresponding subfunction of incoming data*/ + (*sys_event_set)(stp_core_ctx.parser.type); + + stp_ctx_lock(&stp_core_ctx); + + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + + /*Send tx ack*/ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); + } + else + { + stp_process_packet_fail_count++; + /*Queue is full*/ + if(stp_core_ctx.parser.type == GPS_TASK_INDX) + { + /*Clear Rx Queue if GPS*/ + mtk_wcn_stp_flush_rx_queue(GPS_TASK_INDX); + } + else + { + /*notify corresponding subfunction of incoming data*/ + (*sys_event_set)(stp_core_ctx.parser.type); + } + /*enqueue fail, don't send ack and wait for peer retry*/ + STP_ERR_FUNC("Enqueue to Rx queue fail, maybe function %d queue is full\n", stp_core_ctx.parser.type); + } + } + /*sequence not match && previous packet enqueue successfully, send the previous ACK*/ + else if(fgRxOk == 0) + { + STP_ERR_FUNC("mtkstp_process_packet: expected_rxseq = %d, parser.seq = %d\n", stp_core_ctx.sequence.expected_rxseq, stp_core_ctx.parser.seq); + stp_process_packet_fail_count++; + + stp_ctx_lock(&stp_core_ctx); + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 1); + stp_ctx_unlock(&stp_core_ctx); + STP_ERR_FUNC("sequence not match && previous packet enqueue successfully, send the previous ACK (ack no =%d)\n", txAck); + } + /*sequence not match && previous packet enqueue failed, do nothing, make the other side timeout*/ + else + { + stp_process_packet_fail_count++; + STP_ERR_FUNC("sequence not match && previous packet enqueue failed, do nothing, make the other side timeout\n"); + } + + if(fgTriggerResume == 0) + { + /*[PatchNeed]Just Notificaiton, not blocking call*/ + (*sys_event_tx_resume)(stp_core_ctx.sequence.winspace); // notify adaptation layer for possible tx resume mechanism + } + + if(stp_process_packet_fail_count > MTKSTP_RETRY_LIMIT) + { + stp_process_packet_fail_count = 0; + STP_ERR_FUNC("The process packet fail count > 10 lastly\n\r, whole chip reset\n\r"); + #if WMT_PLAT_ALPS + stop_log(); //dump_uart_history(); + #endif + mtk_wcn_stp_dbg_dump_package(); + stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx)); + + /*Whole Chip Reset Procedure Invoke*/ + /*if(STP_NOT_ENABLE_DBG(stp_core_ctx))*/ + { + //(*sys_dbg_assert_aee)("[MT662x]Ack Miss", "**STP Ack Miss**\n Ack Miss.\n"); + osal_dbg_assert_aee("[MT662x]Ack Miss", "**STP Ack Miss**\n Ack Miss.\n"); + + if(STP_IS_ENABLE_RST(stp_core_ctx)) + { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } + else + { + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + } + + return; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_init +* DESCRIPTION +* init STP kernel +* PARAMETERS +* cb_func [IN] function pointers of system APIs +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func) +{ + INT32 ret = 0; + INT32 i = 0; + + /* Function pointer to point to the currently used transmission interface + */ + sys_if_tx = cb_func->cb_if_tx; + + /* Used to inform the function driver has received the corresponding type of information*/ + sys_event_set = cb_func->cb_event_set; + + /* Used to inform the function driver can continue to send information and + STP has resources to deal with + */ + sys_event_tx_resume = cb_func->cb_event_tx_resume; + + /* STP driver determines whether the function is enable. If not enable and + STP has received the kind of information, and STP have the right to put it away. + */ + sys_check_function_status = cb_func->cb_check_funciton_status; + + stp_ctx_lock_init(&stp_core_ctx); + + /* Setup timer to be used to check if f/w receive the data in the specific time + interval after being sent + */ + for(i = 0; i < MTKSTP_MAX_TASK_NUM; i++) + { + osal_unsleepable_lock_init(&stp_core_ctx.ring[i].mtx); + } + stp_core_ctx.tx_timer.timeoutHandler = stp_tx_timeout_handler; + stp_core_ctx.tx_timer.timeroutHandlerData = 0; + osal_timer_create(&stp_core_ctx.tx_timer); + + STP_SET_BT_STK(stp_core_ctx, 0); + STP_SET_ENABLE(stp_core_ctx, 0); + STP_SET_ENABLE_DBG(stp_core_ctx, 0); + STP_SET_ENABLE_RST(stp_core_ctx, 0); + STP_SET_PENDING_TYPE(stp_core_ctx, 0); + STP_SET_READY(stp_core_ctx, 0); + STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, 0); + STP_SET_PSM_CORE(stp_core_ctx, stp_psm_init()); + STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, 0); + STP_ENABLE_FW_COREDUMP(stp_core_ctx, 0); + STP_SET_WMT_LAST_CLOSE(stp_core_ctx,0); + + if(!STP_PSM_CORE(stp_core_ctx)) + { + ret = (-3); + goto ERROR; + } + + STP_SET_BTM_CORE(stp_core_ctx, stp_btm_init()); + if(!STP_BTM_CORE(stp_core_ctx)) + { + STP_ERR_FUNC("STP_BTM_CORE(stp_core_ctx) initialization fail!\n") + ret = (-3); + goto ERROR; + } + + if(STP_BTM_CORE(stp_core_ctx) != NULL) + { + g_mtkstp_dbg = stp_dbg_init(STP_BTM_CORE(stp_core_ctx)); + } + else + { + g_mtkstp_dbg = stp_dbg_init(NULL); + } + + if(!g_mtkstp_dbg) + { + STP_ERR_FUNC("g_mtkstp_dbg initialization fail!\n"); + ret = (-3); + goto ERROR; + } + STP_SET_ENABLE_RST(stp_core_ctx, 1); +#ifdef CONFIG_LOG_STP_INTERNAL + mtk_wcn_stp_dbg_enable(); +#else + mtk_wcn_stp_dbg_enable(); +#endif + goto RETURN; + +ERROR: + stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); + +RETURN: + return ret; + +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_deinit +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +INT32 mtk_wcn_stp_deinit(void) +{ + + sys_if_tx = NULL; + sys_event_set = NULL; + sys_event_tx_resume = NULL; + sys_check_function_status = NULL; + + stp_dbg_deinit(g_mtkstp_dbg); + stp_btm_deinit(STP_BTM_CORE(stp_core_ctx)); + stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_btm_get_dmp +* DESCRIPTION +* get stp dump related information +* PARAMETERS +* buffer: dump placement, len: dump size +* RETURNS +* 0: Success Negative Value: Fail +*****************************************************************************/ + +INT32 mtk_wcn_stp_btm_get_dmp(CHAR *buf, INT32 *len) +{ + return stp_dbg_dmp_out(g_mtkstp_dbg, buf, len); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_notify_stp +* DESCRIPTION +* WMT notification to STP that power saving job is done or not +* PARAMETERS +* +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +INT32 mtk_wcn_stp_psm_notify_stp(const MTKSTP_PSM_ACTION_T action){ + return stp_psm_notify_stp(STP_PSM_CORE(stp_core_ctx), action); +} + +INT32 mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state){ + return stp_psm_set_state(STP_PSM_CORE(stp_core_ctx), state); +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_enable +* DESCRIPTION +* enable STP sleep/wakeup support +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +INT32 mtk_wcn_stp_psm_enable(INT32 idle_time_to_sleep) +{ +#if 0 + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) + { + if( mtk_wcn_stp_is_ready()) + { + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + } + else + { + if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_fullset_mode()) + { + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + } + else if (mtk_wcn_stp_is_sdio_mode()) + { + stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + STP_DBG_FUNC("PSM is not support under SDIO mode\n"); + return 0; + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + } +#else + if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_fullset_mode()) + { + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + } + else if (mtk_wcn_stp_is_sdio_mode()) + { + stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + STP_DBG_FUNC("PSM is not support under SDIO mode\n"); + return 0; + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } +#endif +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP sleep/wakeup support +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_psm_disable(VOID) +{ +#if 0 + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) + { + if( mtk_wcn_stp_is_ready()) + { + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + } + else + { + if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_fullset_mode()) + { + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + else if (mtk_wcn_stp_is_sdio_mode()) + { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + return 0; + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + } +#else + if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_fullset_mode()) + { + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + else if (mtk_wcn_stp_is_sdio_mode()) + { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + return 0; + } + else + { + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } +#endif +} + +extern INT32 mtk_wcn_stp_psm_reset(VOID) +{ + return stp_psm_reset(STP_PSM_CORE(stp_core_ctx)); +} + +extern INT32 mtk_wcn_stp_dbg_disable(VOID) +{ + if(STP_IS_ENABLE_DBG(stp_core_ctx)) + { + STP_INFO_FUNC("STP dbg mode is turned off\n"); + STP_SET_ENABLE_DBG(stp_core_ctx, 0); + stp_dbg_disable(g_mtkstp_dbg); + } + else + { + STP_WARN_FUNC("STP dbg mode has been turned off\n"); + } + + return 0; +} + +extern INT32 mtk_wcn_stp_dbg_enable(VOID) +{ + if(STP_NOT_ENABLE_DBG(stp_core_ctx)) + { + STP_INFO_FUNC("STP dbg mode is turned on\n"); + STP_SET_ENABLE_DBG(stp_core_ctx, 1); + stp_dbg_enable(g_mtkstp_dbg); + } + else + { + STP_WARN_FUNC("STP dbg mode has been turned on\n") + } + + return 0; +} + +INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on) +{ + stp_dbg_log_ctrl (on); + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on) +{ + STP_ENABLE_FW_COREDUMP(stp_core_ctx, on); + STP_INFO_FUNC("%s coredump function.\n", 0 == on ? "disable" : "enable") + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_get(VOID) +{ + return STP_ENABLE_FW_COREDUMP_FLAG(stp_core_ctx); +} + + + + + + + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 0 = sucess; -1 = crc/checksum error +*****************************************************************************/ +INT32 mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + INT32 i; + UINT8 *p_data; + UINT8 padding_len = 0; + INT32 remain_length; // GeorgeKuo: sync from MAUI, change to unsigned + MTK_WCN_BOOL is_function_active = 0; +#ifdef DEBUG_DUMP_PACKET_HEAD + static UINT32 counter = 0; + STP_TRACE_FUNC("++, rx (cnt=%d,len=%d)\n", ++counter, length); +#endif + +#if 0 +#ifdef CONFIG_POWER_SAVING_SUPPORT + if(stp_is_apply_powersaving()) { + //If now chip is awake, to restart monitor! + if(!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))){ + STP_DBG_FUNC("To restart moinotr when rx\n\r"); + stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); + } + } +#endif +#endif + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + /* George FIXME: WHY or HOW can we reduct the locked region? */ + /*flags = (*sys_mutex_lock)(stp_core_ctx.stp_mutex);*/ + i = length; + p_data = (UINT8 *)buffer; + +// stp_dump_data(buffer, "rx queue", length); + + /*STP is not enabled and only WMT can use Raw data path*/ + if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == STP_PENDING_TYPE(stp_core_ctx)) + { + //(*sys_dbg_print)("mtk_wcn_stp_parser_data, buff = %x %x %x %x %x %x %x %x %x %x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); + stp_add_to_rx_queue(buffer, length, STP_PENDING_TYPE(stp_core_ctx)); //route to task who send command + + /* mike: notify corresponding subfunction of incoming data */ + (*sys_event_set)(STP_PENDING_TYPE(stp_core_ctx)); + } + // STP over SDIO + else if ( (mtk_wcn_stp_is_sdio_mode()||mtk_wcn_stp_is_uart_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) + { +#if !(REMOVE_USELESS_LOG) + if(gStpDbgLvl >= STP_LOG_DBG) + { + stp_dump_data(buffer, "sdio parser_in", length); + } +#endif + //STP_DBG_FUNC("sdio stp parser data length = %d\n", length); + while ( i > 0 ) { + switch ( stp_core_ctx.parser.state ) + { + case MTKSTP_SYNC: // b'10 + //if (((*p_data & 0x80) == 0x80) && ((*p_data & 0x40) == 0x00)) + //if(*p_data == 0x80) + if((*p_data & 0x80) == 0x80) + { + //STP_DBG_FUNC("[STP] STP Packet Start =========> \n"); + if(*p_data != 0x80) { + STP_WARN_FUNC("SDIO not 0x80!!(0x%x)\n", *p_data); + } + + if (i >= 4) { +#if !(REMOVE_USELESS_LOG) + if (gStpDbgLvl >= STP_LOG_DBG) {/*print header, when get the full STP header*/ + INT32 type = (*(p_data+1) & 0x70) >> 4; + PCHAR type_name =""; + + //if(type == BT_TASK_INDX){ + if(type == BT_TASK_INDX) + type_name="< BT>"; + else if(type == GPS_TASK_INDX) + type_name=""; + else if(type == WMT_TASK_INDX) + type_name=""; + else if(type == FM_TASK_INDX) + type_name="< FM>"; + + STP_DBG_FUNC("STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", + *p_data, *(p_data+1), *(p_data+2), *(p_data+3), + type_name, + ((*(p_data+1) & 0x0f) << 8) + *(p_data+2), + (*p_data & 0x38) >> 3, + *p_data & 0x07 ); + } +#endif + } + else{ + STP_WARN_FUNC("STP Rx: discard due to i < 4 (%d)\n", i); + } + + //STP_DBG_FUNC("[STP] sync->nak\n"); + stp_change_rx_state(MTKSTP_NAK); + stp_core_ctx.rx_counter++; + } + else + { + STP_WARN_FUNC("sync to sync!!(0x%x)\n", *p_data); + stp_change_rx_state(MTKSTP_SYNC); + } + break; + + case MTKSTP_NAK: + //STP_DBG_FUNC("[STP] nak->length\n"); + stp_change_rx_state(MTKSTP_LENGTH); + stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; + if ( stp_core_ctx.parser.type <= MTKSTP_MAX_TASK_NUM ) + { + stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; + stp_core_ctx.rx_counter++; + } + else + { + STP_WARN_FUNC("nak to sync\n"); + stp_change_rx_state(MTKSTP_SYNC); + } + break; + + case MTKSTP_LENGTH: + //STP_DBG_FUNC("[STP] length -> checksum\n"); + stp_change_rx_state(MTKSTP_CHECKSUM); + stp_core_ctx.parser.length += *p_data; + + /*Valid length checking*/ + if(stp_core_ctx.parser.length < 2000){ + stp_core_ctx.rx_counter++; + } else { + STP_WARN_FUNC("The length of STP packet is not valid !!! length = %d\n", stp_core_ctx.parser.length); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + //return -1; + } + + break; + + case MTKSTP_CHECKSUM: + + if ((stp_core_ctx.parser.type == STP_TASK_INDX)|| + (stp_core_ctx.parser.type == INFO_TASK_INDX)){ + stp_change_rx_state(MTKSTP_FW_MSG); + stp_core_ctx.rx_counter = 0; + i -= 1; + if(i != 0){ + p_data += 1; + } + continue; + } + + if (stp_core_ctx.parser.length == 0) + { + STP_WARN_FUNC("checksum to sync\n"); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + } + else + { + //STP_DBG_FUNC("[STP] checksum->data\n"); + stp_change_rx_state(MTKSTP_DATA); + stp_core_ctx.rx_counter = 0; + } + break; + + case MTKSTP_DATA: + + /* block copy instead of byte copy */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) + { + /*boundary checking*/ + if(stp_core_ctx.rx_counter + remain_length >= MTKSTP_BUFFER_SIZE){ + STP_ERR_FUNC("Abnormal!! Memory operation over boundary!!\n"); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + return -1; + } + + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_core_ctx.parser.state = MTKSTP_CRC1; + continue; + + } + else /* only copy by data length*/ + { + /*fixed klocwork insight issue*/ + /*boundary checking*/ + if(i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE){ + STP_ERR_FUNC("Abnormal!! Memory operation over boundary 2!!\n"); + stp_core_ctx.rx_counter = 0; + return -1; + } + + osal_memcpy( stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; //all remain buffer are data + i = 0; + p_data += i; + continue; + } + break; + + case MTKSTP_CRC1: + stp_change_rx_state(MTKSTP_CRC2); + break; + + case MTKSTP_CRC2: + + /*SDIO mode do it.*/ + if(mtk_wcn_stp_is_sdio_mode()){ + /*STP packet 4-bytes alignment*/ + /*Discard padding bytes , otherwise make parser state machine disorder*/ + if(i <= 4) + { + /*STP_DBG_FUNC("STP last block padding %d bytes\n", i-1);*/ + p_data += (i-1); + i -= (i-1); + } + else + { + padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03))& 0x03; + p_data += padding_len; + i -= padding_len; + /*STP_DBG_FUNC("STP Agg padding %d bytes \n", padding_len);*/ + } + } + stp_dbg_pkt_log(stp_core_ctx.parser.type, + 0, + 0, + 0, + PKT_DIR_RX, + stp_core_ctx.rx_buf, + stp_core_ctx.rx_counter); + if((stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) + { + INT32 b; + + /*Indicate packet to hci_stp*/ + if(gStpDbgLvl >= STP_LOG_DBG) + { + stp_dump_data(stp_core_ctx.rx_buf, "indicate_to_bt_core" , stp_core_ctx.rx_counter); + } + + b=mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if(b) + { + STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); + } + } + else { + + is_function_active = ((*sys_check_function_status)(stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) == STATUS_FUNCTION_ACTIVE); + + /*check type and function if active?*/ + if((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) && (is_function_active == MTK_WCN_BOOL_TRUE)) + { + stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, \ + stp_core_ctx.parser.type); + + /*notify corresponding subfunction of incoming data*/ + (*sys_event_set)(stp_core_ctx.parser.type); + } + else + { + if(is_function_active == MTK_WCN_BOOL_FALSE) + { + STP_ERR_FUNC("function type = %d is inactive, so no en-queue to rx\n", stp_core_ctx.parser.type); + } + else + { + STP_ERR_FUNC("mtkstp_process_packet: type = %x, the type is invalid\n", stp_core_ctx.parser.type); + } + } + } + + //STP_DBG_FUNC("[STP] crc2->sync\n"); + //STP_DBG_FUNC("[STP] STP Packet End <========= \n"); + stp_core_ctx.rx_counter = 0; + stp_change_rx_state(MTKSTP_SYNC); + + break; + + case MTKSTP_FW_MSG: + + /*f/w assert and exception information*/ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) + { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + } + + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + + if (i >= remain_length) + { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; + /*Trace32 Dump*/ + if(stp_core_ctx.parser.type == STP_TASK_INDX){ +// g_block_tx = 1; + mtk_wcn_stp_coredump_start_ctrl(1); + osal_dbg_print("[len=%d][type=%d]\n%s\n",stp_core_ctx.rx_counter, stp_core_ctx.parser.type , stp_core_ctx.rx_buf); + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP /*STP_DBG_FW_ASSERT*/,5,0,0,0,0, + (stp_core_ctx.rx_counter + 1), + stp_core_ctx.rx_buf); + } + + /*discard CRC*/ + //we will discard antoher CRC on the outer switch procedure. + if(i >= 1){ + STP_INFO_FUNC("crc discard.. i = %d\n", i); + i-=1; + if(i > 0){ + p_data+=1; + } + } + + /*STP packet 4-bytes alignment*/ + /*Discard padding bytes , otherwise make parser state machine disorder*/ + if(i <= 4) + { + STP_INFO_FUNC("\n[STP]FW_EVENT========= block padding %d bytes =========\n", i-1); + p_data += (i-1); + i -= (i-1); + } + else + { + padding_len = (0x04 - ((stp_core_ctx.parser.length+6) & 0x03))& 0x03; + p_data += padding_len; + i -= padding_len; + STP_INFO_FUNC("\n[STP]FW_EVENT========= STP Agg padding %d bytes =========\n", padding_len); + } + stp_change_rx_state(MTKSTP_SYNC); + + } + else /* only copy by data length*/ + { + STP_ERR_FUNC("raw data doesn't contain full stp packet!!\n"); + } + break; + default: + break; + } + p_data++; + i--; + } + } + + // STP over UART + else if ( mtk_wcn_stp_is_uart_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) + { + while (i > 0) + { + switch (stp_core_ctx.parser.state) + { + + case MTKSTP_RESYNC1: // RESYNC must be 4 _continuous_ 0x7f + if (*p_data == 0x7f) + { + stp_change_rx_state(MTKSTP_RESYNC2); + } + else + { + stp_change_rx_state(MTKSTP_RESYNC1); + } + break; + case MTKSTP_RESYNC2: + if (*p_data == 0x7f) + { + stp_change_rx_state(MTKSTP_RESYNC3); + } + else + { + stp_change_rx_state(MTKSTP_RESYNC1); + } + break; + case MTKSTP_RESYNC3: + if (*p_data == 0x7f) + { + stp_change_rx_state(MTKSTP_RESYNC4); + } + else + { + stp_change_rx_state(MTKSTP_RESYNC1); + } + break; + case MTKSTP_RESYNC4: + if (*p_data == 0x7f) + { + stp_change_rx_state(MTKSTP_SYNC); + } + else + { + stp_change_rx_state(MTKSTP_RESYNC1); + } + break; + case MTKSTP_SYNC: // b'10 + STP_DUMP_PACKET_HEAD(p_data, "rx (uart):", length > 4 ? 4 : length); + if (((*p_data & 0x80) == 0x80) && + ((*p_data & 0x40) == 0x00)) + { + stp_change_rx_state(MTKSTP_NAK); + stp_core_ctx.parser.seq = (*p_data & 0x38) >> 3; + stp_core_ctx.parser.ack = *p_data & 0x07; + stp_core_ctx.rx_buf[0] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + //stp_core_ctx.rx_counter++; + + if(i >= 4 && gStpDbgLvl >= STP_LOG_DBG){/*print header, when get the full STP header*/ +#if !(REMOVE_USELESS_LOG) + INT32 type = (*(p_data+1) & 0x70) >> 4; + PCHAR type_name =""; + if(type == BT_TASK_INDX) + type_name="< BT>"; + else if(type == GPS_TASK_INDX) + type_name=""; + else if(type == WMT_TASK_INDX) + type_name=""; + else if(type == FM_TASK_INDX) + type_name="< FM>"; + + STP_DBG_FUNC("STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", + *p_data, *(p_data+1), *(p_data+2), *(p_data+3), + type_name, + ((*(p_data+1) & 0x0f) << 8) + *(p_data+2), + (*p_data & 0x38) >> 3, + *p_data & 0x07 ); +#endif + } + else{ + STP_DBG_FUNC("STP Rx: discard due to i < 4\n"); + } + } + else if ((*p_data == 0x7f) && (prev_state == MTKSTP_RESYNC4)) // if this 0x7f is continuous to resync pattern + { + // skip this continuous 0x7f, remain current & prev state + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: continuous resync pattern, buff = %x\n", *p_data); + } + else if (*p_data == 0x7f) // a start of 0x7f, maybe this is resync pattern + { + stp_change_rx_state(MTKSTP_RESYNC2); + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: go to MTKSTP_RESYNC2, buff = %x\n", *p_data); + } + else if (*p_data == 0x55) // STP delimiter + { + // do nothing for delimiter + } + else // unexpected, go to resync1 + { + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: unexpected data, buff = %x\n", *p_data); + } + break; + + case MTKSTP_NAK: + //(*sys_dbg_print)("MTKSTP_NAK : mtk_wcn_stp_parser_data, buff = %x", *p_data); + if(fgEnableNak == 0) + { + stp_core_ctx.parser.nak = 0; // disable NAK + } + else + { + stp_core_ctx.parser.nak = (*p_data & 0x80) >> 7; + } + stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; + stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; + stp_core_ctx.rx_buf[1] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + /*stp_core_ctx.rx_counter++;*/ + if(stp_core_ctx.parser.nak) + { + STP_ERR_FUNC("MTKSTP_NAK TRUE: mtk_wcn_stp_parser_data, buff = %x\n", *p_data); + } + if(stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) + { + stp_change_rx_state(MTKSTP_LENGTH); + } + else + { + stp_change_rx_state(MTKSTP_SYNC); + } + break; + + case MTKSTP_LENGTH: + //(*sys_dbg_print)("MTKSTP_LENGTH : mtk_wcn_stp_parser_data, buff = %x", *p_data); + stp_change_rx_state(MTKSTP_CHECKSUM); + stp_core_ctx.parser.length += *p_data; + + /*Valid length checking*/ + if(stp_core_ctx.parser.length > 2048) + { + STP_ERR_FUNC("The length of STP packet is not valid !!! length = %d\n", stp_core_ctx.parser.length); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + STP_TRACE_FUNC("--\n"); + return -1; + } + + stp_core_ctx.rx_buf[2] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + /*stp_core_ctx.rx_counter++;*/ + break; + + case MTKSTP_CHECKSUM: + //(*sys_dbg_print)("MTKSTP_CHECKSUM : mtk_wcn_stp_parser_data, buff = %x", *p_data); + if ((stp_core_ctx.parser.type == STP_TASK_INDX)|| + (stp_core_ctx.parser.type == INFO_TASK_INDX)) + { + stp_change_rx_state(MTKSTP_FW_MSG); + stp_core_ctx.rx_counter = 0; + i -= 1; + if(i != 0) + { + p_data += 1; + } + continue; + } + + if (((stp_core_ctx.rx_buf[0] + + stp_core_ctx.rx_buf[1] + + stp_core_ctx.rx_buf[2]) & 0xff) == *p_data) + { + // header only packet + if (stp_core_ctx.parser.length == 0) + { + INT32 fgTriggerResume = (-1); + + stp_ctx_lock(&stp_core_ctx); + if(stp_core_ctx.inband_rst_set == 0) + { + stp_dbg_pkt_log(STP_TASK_INDX, + stp_core_ctx.parser.ack, + stp_core_ctx.parser.seq, + 5,//STP type id + PKT_DIR_RX, + NULL, + 0); + fgTriggerResume = stp_process_rxack(); + if(fgTriggerResume == 0) + { + (*sys_event_tx_resume)(stp_core_ctx.sequence.winspace); // notify adaptation layer for possible tx resume mechanism + } + } else { + STP_WARN_FUNC("Now it's inband reset process and drop ACK packet.\n"); + } + stp_ctx_unlock(&stp_core_ctx); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + } + else + { + stp_change_rx_state(MTKSTP_DATA); + stp_core_ctx.rx_counter = 0; + } + } + else + { + STP_ERR_FUNC("The checksum of header is error !!! %02x %02x %02x %02x\n", stp_core_ctx.rx_buf[0], stp_core_ctx.rx_buf[1], stp_core_ctx.rx_buf[2], *p_data); + /* George FIXME: error handling mechanism shall be refined */ + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + + /* since checksum error is usually related to interface + * buffer overflow, so we just let timeout mechanism to + * handle such error. + */ + STP_TRACE_FUNC("--\n"); + /* return and purge COMM port */ + return -1; + /*stp_send_ack(1); NAK mechanism is removed */ + } + break; + + case MTKSTP_DATA: +#if 0 + if (stp_core_ctx.rx_counter < stp_core_ctx.parser.length) + { + stp_core_ctx.rx_buf[stp_core_ctx.rx_counter] = *p_data; + stp_core_ctx.rx_counter++; + } + if (stp_core_ctx.rx_counter == stp_core_ctx.parser.length) + { + stp_change_rx_state(MTKSTP_CRC1); + } +#else + /* block copy instead of byte copy */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) + { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) + { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, remain_length); + + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_core_ctx.parser.state = MTKSTP_CRC1; + continue; + } + else /* only copy by data length*/ + { + /*fixed klocwork insight issue*/ + if(i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) + { + STP_ERR_FUNC("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + STP_TRACE_FUNC("--\n"); + return -1; + } + + osal_memcpy( stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; //all remain buffer are data + i = 0; + p_data += i; + continue; + } +#endif + break; + + case MTKSTP_CRC1: + stp_change_rx_state(MTKSTP_CRC2); + stp_core_ctx.parser.crc = *p_data; + break; + case MTKSTP_CRC2: + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.parser.crc += (*p_data) << 8; + if (stp_check_crc(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, stp_core_ctx.parser.crc) == MTK_WCN_BOOL_TRUE) + { + if(stp_core_ctx.inband_rst_set == 0) + { + stp_process_packet(); + } else { + STP_WARN_FUNC("Now it's inband reset process and drop packet.\n"); + } + } + else + { + STP_ERR_FUNC("The CRC of packet is error !!!\n"); + /* George FIXME: error handling mechanism shall be refined */ + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + + /* since checksum error is usually related to interface + * buffer overflow, so we just let timeout mechanism to + * handle such error. + */ + STP_TRACE_FUNC("--\n"); + /* return and purge COMM port */ + return -1; + /*stp_send_ack(1); NAK mechanism is removed */ + } + break; + + case MTKSTP_FW_MSG: + if (STP_IS_READY(stp_core_ctx)) { + #if WMT_PLAT_ALPS + stop_log(); + #endif + mtk_wcn_stp_dbg_dump_package(); + stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx)); + } + STP_SET_READY(stp_core_ctx, 0); + /*stp inband reset*/ + if (stp_core_ctx.parser.type == STP_TASK_INDX && + stp_core_ctx.parser.seq == 0 && + stp_core_ctx.parser.ack == 0 && + stp_core_ctx.parser.length == 0 && + stp_core_ctx.inband_rst_set == 1) + { + STP_INFO_FUNC("Inband reset event get! Resync STP with firmware!\n\r"); + stp_rest_ctx_state(); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.inband_rst_set = 0; + //STP_INFO_FUNC("Restart STP Timer\n\r"); + //(*sys_timer_start)(stp_core_ctx.tx_timer, mtkstp_tx_timeout, (MTK_WCN_TIMER_CB)stp_tx_timeout_handler, NULL); + STP_TRACE_FUNC("--\n"); + return 0; + } + + /*f/w assert and exception information*/ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) + { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_change_rx_state(MTKSTP_SYNC); + *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; + //STP_ERR_FUNC("%s [%d]\n", stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + #if 0 + if((stp_core_ctx.rx_counter == 1) && (stp_core_ctx.rx_buf[0] == 0xFF)) + { + //For MT6620, enable/disable coredump function is controlled by firmware for the moment, we need to set coredump enable flag to be 1 after + //see firmware send a pariticallar charactor(0xff) before any coredump packet is sent + mtk_wcn_stp_coredump_flag_ctrl(1); + } + #endif + /*Trace32 Dump*/ + if(STP_IS_ENABLE_DBG(stp_core_ctx) && (stp_core_ctx.parser.type == STP_TASK_INDX) && (0 != mtk_wcn_stp_coredump_flag_get())){ + if (0 != stp_core_ctx.rx_counter) + { + STP_SET_READY(stp_core_ctx, 0); + mtk_wcn_stp_coredump_start_ctrl(1); + stp_psm_set_sleep_disable(stp_core_ctx.psm); + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP/*STP_DBG_FW_ASSERT*/,STP_TASK_INDX,0,0,0,0, + (stp_core_ctx.rx_counter + 1), + stp_core_ctx.rx_buf); + } + osal_dbg_print("[len=%d][type=%d]\n%s\n",stp_core_ctx.rx_counter, stp_core_ctx.parser.type , stp_core_ctx.rx_buf); + if (0 == osal_strncmp("coredump end", stp_core_ctx.rx_buf + stp_core_ctx.rx_counter - osal_strlen("coredump end") - 2, osal_strlen("coredump end"))) + { + STP_ERR_FUNC("coredump end\n"); + mtk_wcn_stp_coredump_start_ctrl(0); + stp_psm_set_sleep_enable(stp_core_ctx.psm); + stp_btm_reset_btm_wq(STP_BTM_CORE(stp_core_ctx)); + if(STP_IS_ENABLE_RST(stp_core_ctx)){ + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + }else{ + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + } + /*Runtime FW Log*/ + else if(STP_IS_ENABLE_DBG(stp_core_ctx)&& (stp_core_ctx.parser.type == INFO_TASK_INDX)){ + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_LOG,STP_TASK_INDX,5,0,0,0, + (stp_core_ctx.rx_counter + 1), + stp_core_ctx.rx_buf); + mtk_wcn_stp_dbg_dump_package(); + } + /*Normal mode: whole chip reset*/ + else + { + /*Aee Kernel Warning Message Shown First*/ + //(*sys_dbg_assert_aee)("[MT662x]f/w Assert", stp_core_ctx.rx_buf); + mtk_wcn_stp_coredump_start_ctrl(0); + mtk_wcn_stp_dbg_dump_package(); + + if (0 == mtk_wcn_stp_coredump_flag_get()) { + STP_ERR_FUNC("fw error happend but coredump disabled\n"); + } else { + osal_dbg_assert_aee(stp_core_ctx.rx_buf, stp_core_ctx.rx_buf); + } + + /*Whole Chip Reset Procedure Invoke*/ + if(STP_IS_ENABLE_RST(stp_core_ctx)){ + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + }else{ + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + + /*discard CRC*/ + if(i >= 2){ + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i-=2; + if(i > 0){ + p_data+=2; + } + } + continue; + } + else /* only copy by data length*/ + { + /*fixed klocwork insight issue*/ + if(i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) + { + STP_ERR_FUNC("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + return -1; + } + osal_memcpy( stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; //all remain buffer are data + i = 0; + p_data += i; + continue; + } + + break; + default: + break; + } + p_data++; + i--; + } + } + /* George FIXME: WHY or HOW can we reduct the locked region? */ + /*(*sys_mutex_unlock)(stp_core_ctx.stp_mutex, flags);*/ + STP_TRACE_FUNC("--\n"); + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_enable +* DESCRIPTION +* enable/disable STP +* PARAMETERS +* value [IN] 0=disable, others=enable +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_enable(INT32 value) +{ + STP_INFO_FUNC("%s: set the current enable = (%d)\n", __func__, value); + + stp_rest_ctx_state(); + STP_SET_ENABLE(stp_core_ctx, value); + if (!value) + { + mtk_wcn_stp_psm_reset(); + } + else + { +// g_block_tx = 0; + mtk_wcn_stp_coredump_start_ctrl(0); + } + return 0; +} + + +INT32 mtk_wcn_stp_dbg_dump_package(VOID){ + if(STP_NOT_ENABLE(stp_core_ctx)){ + STP_INFO_FUNC("STP dbg mode is off\n"); + + } else { + STP_INFO_FUNC("STP dbg mode is on\n"); + //if (0 == g_block_tx) + if (0 == mtk_wcn_stp_coredump_start_get()) + { + stp_dbg_dmp_printk(g_mtkstp_dbg); + } + else + { + STP_INFO_FUNC("assert start flag is set, disable packet dump function\n"); + } + } + return 0; +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/un-ready STP +* PARAMETERS +* value [IN] 0=un-ready, others=ready +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_ready(INT32 value) +{ + STP_INFO_FUNC("set ready (%d)\n", value); + + STP_SET_READY(stp_core_ctx, value); + /*if whole chip reset, reset the debuggine mode*/ +#ifndef CONFIG_LOG_STP_INTERNAL + //mtk_wcn_stp_dbg_disable(); +#endif + + if(stp_is_apply_powersaving()) + { + STP_INFO_FUNC("Restart the stp-psm monitor !!\n"); + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + + return 0; +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value) +{ + STP_INFO_FUNC("set f/w assert (%d)\n", value); + + STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, value); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get f/w assert flag in STP context +* PARAMETERS +* VOID +* RETURNS +* INT32 0= f/w assert flag is not set, others=f/w assert flag is set +*****************************************************************************/ +INT32 mtk_wcn_stp_coredump_start_get(VOID) +{ + return STP_FW_COREDUMP_FLAG(stp_core_ctx); +} + + +/* mtk_wcn_stp_set_wmt_last_close -- set the state of link(UART or SDIO) + * @ value - 1, link already be closed; 0, link is open + * + * Return 0 if success; else error code + */ +INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value) +{ + STP_INFO_FUNC("set wmt_last_close flag (%d)\n", value); + + STP_SET_WMT_LAST_CLOSE(stp_core_ctx, value); + + return 0; +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 > 0: length transmitted; = 0: error +*****************************************************************************/ +INT32 mtk_wcn_stp_send_data(const UINT8 *buffer, const UINT32 length, const UINT8 type) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + UINT8 *p_tx_buf = NULL; + UINT16 crc; + INT32 ret = 0; + + //osal_buffer_dump(buffer,"tx", length, 32); + + if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { + STP_ERR_FUNC("WMT lats close,shoud not have tx request!\n"); + return length; + } + + //if(g_block_tx) + if (0 != mtk_wcn_stp_coredump_start_get()) + { + STP_ERR_FUNC("STP fw coredump start flag set...\n"); + return length; + } + +#ifdef CONFIG_POWER_SAVING_SUPPORT + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) + { + if(type != WMT_TASK_INDX) + { + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0); + } + + //if(stp_is_apply_powersaving()) + { + if(type == WMT_TASK_INDX){ + goto DONT_MONITOR; + } + /*-----------------------------STP_PSM_Lock----------------------------------------*/ + ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); + if (ret) { + STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + if(!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))){ + if(stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))){ + STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); + stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); + } + } else { + ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); + stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + return ret; + } + } + } + else + { + //if(stp_is_apply_powersaving()) + { + if(stp_is_privileges_cmd(buffer, length , type)) + { + STP_DBG_FUNC("send privileges cmd\n"); + goto DONT_MONITOR; + } + //If now chip is awake, to restart monitor! + //STP_INFO_FUNC("check if block traffic !!\n"); + /*-----------------------------STP_PSM_Lock----------------------------------------*/ + ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); + if (ret) { + STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + if(!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) + { + //STP_INFO_FUNC("not to block !!\n"); + if(stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))) + { + STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); + stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); + } + stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); + } + else + { + //STP_INFO_FUNC("to block !!\n"); + + //STP_INFO_FUNC("****************hold data in psm queue data length = %d\n", length); + //stp_dump_data(buffer, "Hold in psm queue", length); + //hold datas + ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); + //wmt notification + STP_INFO_FUNC("#####Type = %d, to inform WMT to wakeup chip, ret = %d\n", type, ret); + stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); + //STP_INFO_FUNC("*********Type = %d, to inform WMT to wakeup chip>end\n", type); + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + return ret; + } + } + } + DONT_MONITOR: +#endif + if(type == BT_TASK_INDX) + { + const static UINT8 rst_buf[4] = {0x01, 0x03, 0x0c, 0x00}; + if(!osal_strncmp(buffer, rst_buf, 4)) + { + osal_printtimeofday("############ BT Rest start -->"); + } + } + + stp_ctx_lock(&stp_core_ctx); + /*Only WMT can set raw data */ + if(STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) + { + //no-op + } + else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) + { + //ret = mtk_wcn_stp_send_data_raw(buffer, length, type); + } + + // STP over SDIO + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) + { + + //osal_printtimeofday("[ STP][SDIO][ B][W]"); + + mtkstp_header[0] = 0x80; + mtkstp_header[1] = (type << 4) + (((length)>>8) & 0x0f); + mtkstp_header[2] = (length) & 0xff; + mtkstp_header[3] = 0x00; + + //HEADER + p_tx_buf = &stp_core_ctx.tx_buf[0]; + osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); + p_tx_buf += MTKSTP_HEADER_SIZE; + + //PAYLOAD + osal_memcpy(p_tx_buf, buffer, length); + p_tx_buf += length; + + //CRC + temp[0] = 0x00; + temp[1] = 0x00; + osal_memcpy(p_tx_buf, temp, 2); + stp_dbg_pkt_log(type, + 0, + 0, + 0, + PKT_DIR_TX, + buffer, + length); + (*sys_if_tx)(&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE+length+2), &ret); + + if ( (MTKSTP_HEADER_SIZE+length+2) != ret ) + { + STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); + osal_assert(0); + ret = 0; + } + else + { + ret = (INT32)length; + } + + //osal_printtimeofday("[ STP][SDIO][ E][W]"); + } + + // STP over UART + else if ( mtk_wcn_stp_is_uart_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) + { + + //osal_printtimeofday("[ STP][UART][ B][W]"); + //STP_INFO_FUNC("Write byte %d\n", length); + + if ((stp_core_ctx.sequence.winspace > 0) && + (stp_core_ctx.inband_rst_set == 0) && + (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) + { + /*Make Header*/ + //(*sys_dbg_print)("mtk_wcn_stp_send_data 1, txseq = %d, winspace = %d", stp_core_ctx.sequence.txseq, stp_core_ctx.sequence.winspace); + mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; + mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); + mtkstp_header[2] = length & 0xff; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; + if (fgEnableDelimiter == 1) + { + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; + stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); + } + stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); + + /*Make Payload*/ + stp_add_to_tx_queue(buffer, length); + + /*Make CRC*/ + crc = osal_crc16(buffer, length); + temp[0] = crc & 0xff; + temp[1] = (crc & 0xff00) >> 8; + stp_add_to_tx_queue(temp, 2); + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, + crc, + PKT_DIR_TX, + buffer, + length); + + /*Kick to UART*/ + stp_send_tx_queue(stp_core_ctx.sequence.txseq); + + INDEX_INC(stp_core_ctx.sequence.txseq); + stp_core_ctx.sequence.winspace--; + + /*Setup the Retry Timer*/ + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + { + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + } + else + { + STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); + } + ret = (INT32)length; + } + else + { + /* + No winspace to send. Let caller retry + */ + if(stp_core_ctx.inband_rst_set == 1) + { + STP_WARN_FUNC("Now it's inband reset process and drop sent packet.\n"); + } + else + { + STP_ERR_FUNC("%s: There is no winspace/txqueue to send !!!\n", __FUNCTION__); + } + ret = 0; + } + + //osal_printtimeofday("[ STP][UART][ E][W]"); + } + stp_ctx_unlock(&stp_core_ctx); + +#ifdef CONFIG_POWER_SAVING_SUPPORT + + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) + { + if(type != WMT_TASK_INDX) + { + stp_psm_notify_wmt_sleep(STP_PSM_CORE(stp_core_ctx)); + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + } + } + else + { + //if(stp_is_apply_powersaving()) + { + if((MTK_WCN_BOOL_FALSE == stp_is_privileges_cmd(buffer, length , type))) + { + + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + } + } + } + #endif + + return ret; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +INT32 mtk_wcn_stp_send_data_raw (const UINT8 *buffer, const UINT32 length, const UINT8 type) +{ + UINT32 written = 0; + INT32 ret = 0; + + if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { + STP_ERR_FUNC("WMT lats close,shoud not have tx request!"); + return length; + } + + STP_DBG_FUNC("mtk_wcn_stp_send_data_raw, type = %d, data = %x %x %x %x %x %x ", type, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + STP_SET_PENDING_TYPE(stp_core_ctx, type); // remember tx type, forward following rx to this type + + stp_ctx_lock(&stp_core_ctx); + stp_dbg_pkt_log( + type, + 0, + 0, + 0, + PKT_DIR_TX, + buffer, + 1); + (*sys_if_tx)(&buffer[0], length, &written); + stp_ctx_unlock(&stp_core_ctx); + + if (written == 0) + { + stp_dump_data(&buffer[0], "tx raw failed:", length); + } + + if(written == length) + { + ret = (INT32)written; + } + else + { + ret = (-1); + } + + return ret; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type) +{ + /* GeorgeKuo modify: reduce "if" branch */ + UINT16 copyLen = 0; + UINT16 tailLen = 0; + if ((MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) && (type != WMT_TASK_INDX)) + { + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1); + } + + stp_ctx_lock(&stp_core_ctx); + while (stp_core_ctx.ring[type].read_p != stp_core_ctx.ring[type].write_p) + { + /* GeorgeKuo modify: reduce if branch */ + if ( stp_core_ctx.ring[type].write_p > stp_core_ctx.ring[type].read_p) + { + copyLen = stp_core_ctx.ring[type].write_p - stp_core_ctx.ring[type].read_p; + if (copyLen > length) + { + copyLen = length; + } + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + break; + } + else + { + tailLen = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].read_p; + if (tailLen > length) + { // exclude equal case to skip wrap check + copyLen = length; + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + } + else + { + // part 1: copy tailLen + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, tailLen); + + buffer += tailLen; //update buffer offset + + // part 2: check if head length is enough + copyLen = length - tailLen; + copyLen = (stp_core_ctx.ring[type].write_p < copyLen) ? stp_core_ctx.ring[type].write_p : copyLen; + + if (copyLen) + { + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + 0, copyLen); + } + + // Update read_p final position + stp_core_ctx.ring[type].read_p = copyLen; + + // update return length: head + tail + copyLen += tailLen; + } + break; + } + } + + stp_ctx_unlock(&stp_core_ctx); + + return copyLen; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +INT32 mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +{ + INT32 ret; + + stp_ctx_lock(&stp_core_ctx); + + if(stp_core_ctx.ring[type].read_p == stp_core_ctx.ring[type].write_p) + { + ret = 1; // queue is empty + } + else + { + ret = 0; // queue is not empty + } + + stp_ctx_unlock(&stp_core_ctx); + + return ret; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ + +void mtk_wcn_stp_set_mode(UINT32 mode) +{ + STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, mode); + + STP_INFO_FUNC("STP_SUPPORT_PROTOCOL = %08x \n", STP_SUPPORT_PROTOCOL(stp_core_ctx)); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Fullset mode, FALSE:Not UART Fullset mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if(STP_SUPPORT_PROTOCOL(stp_core_ctx)& MTKSTP_UART_FULL_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Mandatory mode, FALSE:Not UART Mandotary mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if(STP_SUPPORT_PROTOCOL(stp_core_ctx)& MTKSTP_UART_MAND_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_sdio_mode +* DESCRIPTION +* Is stp use SDIO mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if(STP_SUPPORT_PROTOCOL(stp_core_ctx)& MTKSTP_SDIO_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To sync to oringnal stp state with f/w stp +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +void mtk_wcn_stp_inband_reset(void) +{ + UINT8 inband_reset_packet[64]; + UINT32 txseq = 0; + UINT32 txack = 0; + UINT32 crc =0; + UINT32 ret = 0; + UINT32 reset_payload_len=0; + + /*512 bytes*/ + UINT8 reset_payload[]= { + 0xc0, 0x01, 0xc0, 0xde, 0x3e, 0xd1, 0xa7, 0xef + }; + + stp_ctx_lock(&stp_core_ctx); + + /*RESYNC*/ + inband_reset_packet[0]=0x7f; + inband_reset_packet[1]=0x7f; + inband_reset_packet[2]=0x7f; + inband_reset_packet[3]=0x7f; + inband_reset_packet[4]=0x7f; + inband_reset_packet[5]=0x7f; + inband_reset_packet[6]=0x7f; + inband_reset_packet[7]=0x7f; + + /*header*/ + reset_payload_len = sizeof(reset_payload)/sizeof(reset_payload[0]); + inband_reset_packet[8] = 0x80 + (txseq << 3) + txack; + inband_reset_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); + inband_reset_packet[10] = reset_payload_len & 0xff; + inband_reset_packet[11] = (inband_reset_packet[8] + inband_reset_packet[9] + inband_reset_packet[10]) & 0xff; + + /*payload*/ + osal_memcpy(&inband_reset_packet[12], reset_payload, reset_payload_len); + + /*crc*/ + crc = osal_crc16(&reset_payload[0], reset_payload_len); + inband_reset_packet[12 + reset_payload_len] = crc & 0xff; + inband_reset_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; + + (*sys_if_tx)(&inband_reset_packet[0], 14 + reset_payload_len, &ret); + + if (ret != (14 + reset_payload_len)) + { + STP_ERR_FUNC("Inband sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, ret); + } + + stp_core_ctx.inband_rst_set = 1; + stp_ctx_unlock(&stp_core_ctx); +} + +void mtk_wcn_stp_debug_ctrl(INT32 op, INT32 filter, INT32 filter_param) +{ + return ; +} + +void mtk_wcn_stp_test_cmd(INT32 cmd_no) +{ + UINT8 test_packet[64]; + UINT32 txseq = 0; + UINT32 txack = 0; + UINT32 crc =0; + UINT32 ret = 0; + UINT32 reset_payload_len=0; + + UINT8 test_payload[]= { + 0xAA, 0xAA, 0xC0, 0xDE, 0x3E, 0xD1, 0xA7, 0xEF + }; +// +// select your test command by cmd_no +// +if(cmd_no == 0) +{ + //to test new command to chip + stp_ctx_lock(&stp_core_ctx); + + /*RESYNC*/ + test_packet[0]=0x7f; + test_packet[1]=0x7f; + test_packet[2]=0x7f; + test_packet[3]=0x7f; + test_packet[4]=0x7f; + test_packet[5]=0x7f; + test_packet[6]=0x7f; + test_packet[7]=0x7f; + + /*header*/ + reset_payload_len = sizeof(test_payload)/sizeof(test_payload[0]); + test_packet[8] = 0x80 + (txseq << 3) + txack; + test_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); + test_packet[10] = reset_payload_len & 0xff; + test_packet[11] = (test_packet[8] + test_packet[9] + test_packet[10]) & 0xff; + + /*payload*/ + osal_memcpy(&test_packet[12], test_payload, reset_payload_len); + + /*crc*/ + crc = osal_crc16(&test_payload[0], reset_payload_len); + test_packet[12 + reset_payload_len] = crc & 0xff; + test_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; + + (*sys_if_tx)(&test_packet[0], 14 + reset_payload_len, &ret); + if (ret != (14 + reset_payload_len)) + { + STP_ERR_FUNC("stp test sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, ret); + } + + stp_ctx_unlock(&stp_core_ctx); +} + +} +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush_context +* DESCRIPTION +* Flush STP Context +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +void mtk_wcn_stp_flush_context(void) +{ + stp_rest_ctx_state(); +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush_rx_queue +* DESCRIPTION +* Flush STP Rx Queue +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ + +void mtk_wcn_stp_flush_rx_queue(UINT32 type) +{ + stp_ctx_lock(&stp_core_ctx); + if(type >= 0 && type < MTKSTP_MAX_TASK_NUM) + { + stp_core_ctx.ring[type].read_p = 0; + stp_core_ctx.ring[type].write_p = 0; + } + stp_ctx_unlock(&stp_core_ctx); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* STP is ready? +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_ready(void) +{ + return STP_IS_READY(stp_core_ctx); +} + +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ + +void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) +{ + //g_mtkstp_bluez_flag = bluez_flag; + STP_SET_BT_STK(stp_core_ctx, bluez_flag); +} + +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode) +{ + STP_SET_ENABLE_DBG(stp_core_ctx, dbg_mode); +} + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst) +{ + STP_SET_ENABLE_RST(stp_core_ctx, auto_rst); +} + + +INT32 mtk_wcn_stp_notify_sleep_for_thermal() +{ + return stp_psm_sleep_for_thermal(STP_PSM_CORE(stp_core_ctx)); +} + +EXPORT_SYMBOL(mtk_wcn_stp_dbg_level); + + diff --git a/drivers/mtk_wcn_combo/common/core/stp_exp.c b/drivers/mtk_wcn_combo/common/core/stp_exp.c new file mode 100755 index 000000000000..608add763f28 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/stp_exp.c @@ -0,0 +1,259 @@ +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if 0 //to do---- need check why need this header file +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* udelay() */ + +#include +#include +#endif +#include "stp_core.h" +#include "stp_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static MTK_WCN_STP_IF_TX stp_uart_if_tx = NULL; +static MTK_WCN_STP_IF_TX stp_sdio_if_tx = NULL; +static ENUM_STP_TX_IF_TYPE g_stp_if_type = STP_MAX_IF_TX; +static MTK_WCN_STP_IF_RX stp_if_rx = NULL; +static MTK_WCN_STP_EVENT_CB event_callback_tbl[MTKSTP_MAX_TASK_NUM] = {0x0}; +static MTK_WCN_STP_EVENT_CB tx_event_callback_tbl[MTKSTP_MAX_TASK_NUM] = {0x0}; + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size) +{ + if(stp_if_rx == 0x0) + { + return (-1); + } + else + { + (*stp_if_rx)(data, size); + return 0; + } +} + +static INT32 mtk_wcn_sys_if_tx ( + const UINT8 *data, + const UINT32 size, + UINT32 *written_size + ) +{ + + if (STP_UART_IF_TX == g_stp_if_type) { + return stp_uart_if_tx != NULL ? (*stp_uart_if_tx)(data, size, written_size) : -1; + } + else if (STP_SDIO_IF_TX == g_stp_if_type) { + return stp_sdio_if_tx != NULL ? (*stp_sdio_if_tx)(data, size, written_size) : -1; + } + else { + /*if (g_stp_if_type >= STP_MAX_IF_TX) */ /* George: remove ALWAYS TRUE condition */ + return (-1); + } +} + +static INT32 mtk_wcn_sys_event_set(UINT8 function_type) +{ + if((function_type < MTKSTP_MAX_TASK_NUM) && (event_callback_tbl[function_type] != 0x0)) + { + (*event_callback_tbl[function_type])(); + } + else { + /* FIXME: error handling */ + osal_dbg_print("[%s] STP set event fail. It seems the function is not active.\n", __func__); + } + + return 0; +} + +static INT32 mtk_wcn_sys_event_tx_resume(UINT8 winspace) +{ + int type = 0; + + for(type = 0 ; type < MTKSTP_MAX_TASK_NUM ; type ++ ) + { + if(tx_event_callback_tbl[type]) + { + tx_event_callback_tbl[type](); + } + } + + return 0; +} + +static INT32 mtk_wcn_sys_check_function_status(UINT8 type, UINT8 op){ + + /*op == FUNCTION_ACTIVE, to check if funciton[type] is active ?*/ + if(!(type >= 0 && type < MTKSTP_MAX_TASK_NUM)) + { + return STATUS_FUNCTION_INVALID; + } + + if(op == OP_FUNCTION_ACTIVE) + { + if(event_callback_tbl[type] != 0x0) + { + return STATUS_FUNCTION_ACTIVE; + } + else + { + return STATUS_FUNCTION_INACTIVE; + } + } + /*you can define more operation here ..., to queury function's status/information*/ + + return STATUS_OP_INVALID; +} + +INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +{ + stp_if_rx = func; + + return 0; +} + +VOID mtk_wcn_stp_set_if_tx_type ( + ENUM_STP_TX_IF_TYPE stp_if_type + ) +{ + g_stp_if_type = stp_if_type; + osal_dbg_print("[%s] set STP_IF_TX to %s.\n", + __FUNCTION__, + (STP_UART_IF_TX == stp_if_type)? "UART" : ((STP_SDIO_IF_TX == stp_if_type) ? "SDIO" : "NULL")); +} + +INT32 mtk_wcn_stp_register_if_tx ( + ENUM_STP_TX_IF_TYPE stp_if, + MTK_WCN_STP_IF_TX func + ) +{ + if (STP_UART_IF_TX == stp_if) + { + stp_uart_if_tx = func; + } + else if (STP_SDIO_IF_TX == stp_if) + { + stp_sdio_if_tx = func; + } + else + { + osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __FUNCTION__, stp_if); + return -1; + } + + return 0; +} + +INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +{ + if (type < MTKSTP_MAX_TASK_NUM) + { + event_callback_tbl[type] = func; + + /*clear rx queue*/ + osal_dbg_print("Flush type = %d Rx Queue\n", type); + mtk_wcn_stp_flush_rx_queue(type); + } + + return 0; +} + +INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +{ + if(type < MTKSTP_MAX_TASK_NUM) + { + tx_event_callback_tbl[type] = func; + } + else + { + osal_bug_on(0); + } + + return 0; +} + +INT32 stp_drv_init(VOID) +{ + mtkstp_callback cb = + { + .cb_if_tx = mtk_wcn_sys_if_tx, + .cb_event_set = mtk_wcn_sys_event_set, + .cb_event_tx_resume = mtk_wcn_sys_event_tx_resume, + .cb_check_funciton_status = mtk_wcn_sys_check_function_status + }; + + return mtk_wcn_stp_init(&cb); +} + +VOID stp_drv_exit(VOID) +{ + mtk_wcn_stp_deinit(); + + return; +} + +EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); +EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); +EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); +EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); +EXPORT_SYMBOL(mtk_wcn_stp_parser_data); +EXPORT_SYMBOL(mtk_wcn_stp_send_data); +EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); +EXPORT_SYMBOL(mtk_wcn_stp_receive_data); +EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); +EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); +EXPORT_SYMBOL(mtk_wcn_stp_is_ready); +EXPORT_SYMBOL(mtk_wcn_stp_dbg_log_ctrl); + + + + + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_conf.c b/drivers/mtk_wcn_combo/common/core/wmt_conf.c new file mode 100755 index 000000000000..09a6ecb0aee9 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_conf.c @@ -0,0 +1,525 @@ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CONF]" + + +#include "osal_typedef.h" +//#include "osal.h" +#include "wmt_lib.h" +#include "wmt_dev.h" +#include "wmt_conf.h" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct parse_data { + PCHAR name; + INT32 (*parser)(P_DEV_WMT pWmtDev, const struct parse_data *data,const PCHAR value); + PCHAR (*writer)(P_DEV_WMT pWmtDev, const struct parse_data *data); + /*PCHAR param1, *param2, *param3;*/ + // TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! + PCHAR param1; + PCHAR param2; + PCHAR param3; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +extern DEV_WMT gDevWmt; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +static INT32 wmt_conf_parse_char( + P_DEV_WMT pWmtDev, + const struct parse_data *data, + const PCHAR pos + ); + +static PCHAR wmt_conf_write_char( + P_DEV_WMT pWmtDev, + const struct parse_data *data + ); + +static INT32 wmt_conf_parse_short( + P_DEV_WMT pWmtDev, + const struct parse_data *data, + const PCHAR pos + ); + +static PCHAR wmt_conf_write_short( + P_DEV_WMT pWmtDev, + const struct parse_data *data + ); + +static INT32 wmt_conf_parse_int( + P_DEV_WMT pWmtDev, + const struct parse_data *data, + const PCHAR pos + ); + +static PCHAR wmt_conf_write_int( + P_DEV_WMT pWmtDev, + const struct parse_data *data + ); + +static INT32 wmt_conf_parse_pair ( + P_DEV_WMT pWmtDev, + const PCHAR pKey, + const PCHAR pVal + ); + +static INT32 wmt_conf_parse ( + P_DEV_WMT pWmtDev, + const PCHAR pInBuf, + UINT32 size + ); + +#define OFFSET(v) ((void *) &((P_DEV_WMT) 0)->v) + +#define _CHAR(f) #f, wmt_conf_parse_char, wmt_conf_write_char, OFFSET(rWmtGenConf.f) +#define CHAR(f) _CHAR(f), NULL, NULL + +#define _SHORT(f) #f, wmt_conf_parse_short, wmt_conf_write_short, OFFSET(rWmtGenConf.f) +#define SHORT(f) _SHORT(f), NULL, NULL + +#define _INT(f) #f, wmt_conf_parse_int, wmt_conf_write_int, OFFSET(rWmtGenConf.f) +#define INT(f) _INT(f), NULL, NULL + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static const struct parse_data wmtcfg_fields[] = { + { CHAR(coex_wmt_ant_mode) }, + { CHAR(coex_wmt_wifi_time_ctl) }, + { CHAR(coex_wmt_ext_pta_dev_on) }, + + { CHAR(coex_bt_rssi_upper_limit) }, + { CHAR(coex_bt_rssi_mid_limit) }, + { CHAR(coex_bt_rssi_lower_limit) }, + { CHAR(coex_bt_pwr_high) }, + { CHAR(coex_bt_pwr_mid) }, + { CHAR(coex_bt_pwr_low) }, + + { CHAR(coex_wifi_rssi_upper_limit) }, + { CHAR(coex_wifi_rssi_mid_limit) }, + { CHAR(coex_wifi_rssi_lower_limit) }, + { CHAR(coex_wifi_pwr_high) }, + { CHAR(coex_wifi_pwr_mid) }, + { CHAR(coex_wifi_pwr_low) }, + + { CHAR(coex_ext_pta_hi_tx_tag) }, + { CHAR(coex_ext_pta_hi_rx_tag) }, + { CHAR(coex_ext_pta_lo_tx_tag) }, + { CHAR(coex_ext_pta_lo_rx_tag) }, + { SHORT(coex_ext_pta_sample_t1) }, + { SHORT(coex_ext_pta_sample_t2) }, + { CHAR(coex_ext_pta_wifi_bt_con_trx) }, + + { INT(coex_misc_ext_pta_on) }, + { INT(coex_misc_ext_feature_set) }, + + { CHAR(wmt_gps_lna_pin) }, + { CHAR(wmt_gps_lna_enable) }, + + { CHAR(pwr_on_rtc_slot) }, + { CHAR(pwr_on_ldo_slot) }, + { CHAR(pwr_on_rst_slot) }, + { CHAR(pwr_on_off_slot) }, + { CHAR(pwr_on_on_slot) }, + { CHAR(co_clock_flag) }, + + { INT(sdio_driving_cfg) }, + +}; + +#define NUM_WMTCFG_FIELDS (osal_sizeof(wmtcfg_fields) / osal_sizeof(wmtcfg_fields[0])) + +static INT32 wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, + const PCHAR pos) +{ + PUCHAR dst; + dst = (PCHAR ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + if((osal_strlen(pos) > 2) && + ((*pos)=='0') && (*(pos+1)=='x') ){ + *dst = osal_strtol(pos+2, NULL, 16); + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + *dst = osal_strtol(pos, NULL, 10); + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + return 0; +} + +static PCHAR wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PCHAR src; + INT32 res; + PCHAR value; + + src = (PCHAR ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, + const PCHAR pos) +{ + PUINT16 dst; + dst = (PINT16 ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + //WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); + + if((osal_strlen(pos) > 2) && + ((*pos)=='0') && (*(pos+1)=='x') ){ + *dst = osal_strtol(pos+2, NULL, 16); + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + *dst = osal_strtol(pos, NULL, 10); + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PCHAR wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT16 src; + INT32 res; + PCHAR value; + + // TODO: [FixMe][George] FIX COMPILE WARNING HERE! + src = (PINT16 ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, + const PCHAR pos) +{ + PUINT32 dst; + dst = (PINT32 ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + //WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); + + if((osal_strlen(pos) > 2) && + ((*pos)=='0') && (*(pos+1)=='x') ){ + *dst = osal_strtol(pos+2, NULL, 16); + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + *dst = osal_strtol(pos, NULL, 10); + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PCHAR wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT32 src; + INT32 res; + PCHAR value; + + src = (PUINT32 ) (((PUINT8) pWmtDev) + (LONG) data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_pair ( + P_DEV_WMT pWmtDev, + const PCHAR pKey, + const PCHAR pVal + ) +{ + INT32 i = 0; + INT32 ret = 0; + + //WMT_INFO_FUNC( DBG_NAME "cfg(%s) val(%s) \n", pKey, pVal); + + for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { + const struct parse_data *field = &wmtcfg_fields[i]; + if (osal_strcmp(pKey, field->name) != 0) + continue; + if (field->parser(pWmtDev, field, pVal)) { + WMT_ERR_FUNC("failed to parse %s '%s'.\n", pKey, pVal); + ret = -1; + } + break; + } + if (i == NUM_WMTCFG_FIELDS) { + WMT_ERR_FUNC("unknown field '%s'.\n", pKey); + ret = -1; + } + + return ret; +} + +static INT32 wmt_conf_parse ( + P_DEV_WMT pWmtDev, + const PCHAR pInBuf, + UINT32 size + ) +{ + CHAR *pch; + CHAR * pBuf; + CHAR * pLine; + CHAR * pKey; + CHAR * pVal; + CHAR * pPos; + INT32 ret = 0; + INT32 i = 0; + PCHAR pa = NULL; + + pBuf = osal_malloc(size); + if (!pBuf) { + return -1; + } + + osal_memcpy(pBuf, pInBuf, size); + pBuf[size] = '\0'; + + pch = pBuf; + /* pch is to be updated by strsep(). Keep pBuf unchanged!! */ + + #if 0 + { + PCHAR buf_ptr = pBuf; + INT32 k=0; + WMT_INFO_FUNC("%s len=%d", "wmcfg.content:", size); + for(k=0; k < size ; k++){ + //if(k%16 == 0) WMT_INFO_FUNC("\n"); + WMT_INFO_FUNC("%c", buf_ptr[k]); + } + WMT_INFO_FUNC("--end\n"); + } + #endif + + while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) { + /* pch is updated to the end of pLine by strsep() and updated to '\0' */ + /*WMT_INFO_FUNC("strsep offset(%d), char(%d, '%c' ) \n", pLine-pBuf, *pLine, *pLine);*/ + /* parse each line */ + + // WMT_INFO_FUNC("==> Line = (%s)\n", pLine); + + if (!*pLine) { + continue; + } + + pVal = osal_strchr(pLine, '='); + if (!pVal) { + WMT_WARN_FUNC("mal-format cfg string(%s)\n", pLine); + continue; + } + + /* |<-pLine->|'='<-pVal->|'\n' ('\0')| */ + *pVal = '\0'; /* replace '=' with '\0' to get key */ + /* |<-pKey->|'\0'|<-pVal->|'\n' ('\0')| */ + pKey = pLine; + + if((pVal - pBuf) < size){ + pVal++; + } + + /*key handling*/ + pPos = pKey; + /*skip space characeter*/ + while(((*pPos)==' ') || ((*pPos)=='\t') || ((*pPos)=='\n')){ + if((pPos - pBuf) >= size) + break; + pPos++; + } + /*key head*/ + pKey=pPos; + while(((*pPos)!=' ') && ((*pPos)!='\t') && ((*pPos)!='\0') && ((*pPos)!='\n')){ + if((pPos - pBuf) >= size) + break; + pPos++; + } + /*key tail*/ + (*pPos)='\0'; + + /*value handling*/ + pPos = pVal; + /*skip space characeter*/ + while(((*pPos)==' ') || ((*pPos)=='\t') || ((*pPos)=='\n')){ + if((pPos - pBuf) >= size) + break; + pPos++; + } + /*value head*/ + pVal=pPos; + while(((*pPos)!=' ') && ((*pPos)!='\t') && ((*pPos)!='\0') && ((*pPos)!='\n')){ + if((pPos - pBuf) >= size) + break; + pPos++; + } + /*value tail*/ + (*pPos)='\0'; + + //WMT_DBG_FUNC("parse (key: #%s#, value: #%s#)\n", pKey, pVal); + ret = wmt_conf_parse_pair(pWmtDev, pKey, pVal); + WMT_WARN_FUNC("parse (%s, %s, %d)\n", pKey, pVal, ret); + if (ret) { + WMT_WARN_FUNC("parse fail (%s, %s, %d)\n", pKey, pVal, ret); + } + } + + for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { + const struct parse_data *field = &wmtcfg_fields[i]; + pa = field->writer(pWmtDev, field); + if(pa) + { + WMT_INFO_FUNC("#%d(%s)=>%s\n", i, field->name, pa); + osal_free(pa); + } else { + WMT_ERR_FUNC("failed to parse '%s'.\n", field->name); + } + } + osal_free(pBuf); + return 0; +} + + +INT32 wmt_conf_set_cfg_file(const CHAR *name) +{ + if (NULL == name) + { + WMT_ERR_FUNC("name is NULL\n"); + return -1; + } + if (osal_strlen(name) >= osal_sizeof(gDevWmt.cWmtcfgName)) + { + WMT_ERR_FUNC("name is too long, length=%d, expect to < %d \n", osal_strlen(name), osal_sizeof(gDevWmt.cWmtcfgName)); + return -2; + } + osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); + osal_strcpy(&(gDevWmt.cWmtcfgName[0]), name); + WMT_ERR_FUNC("WMT config file is set to (%s)\n", &(gDevWmt.cWmtcfgName[0])); + + return 0; +} + + +INT32 wmt_conf_read_file(VOID) +{ + INT32 ret = -1; + + osal_memset(&gDevWmt.rWmtGenConf, 0, osal_sizeof(gDevWmt.rWmtGenConf)); + osal_memset(&gDevWmt.pWmtCfg, 0, osal_sizeof(gDevWmt.pWmtCfg)); + + #if 0 + osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); + + osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT_PREFIX, osal_sizeof(CUST_CFG_WMT_PREFIX)); + osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT, osal_sizeof(CUST_CFG_WMT)); + #endif + + if (!osal_strlen(&(gDevWmt.cWmtcfgName[0]))) + { + WMT_ERR_FUNC("empty Wmtcfg name\n"); + osal_assert(0); + return ret; + } + WMT_INFO_FUNC("WMT config file:%s\n", &(gDevWmt.cWmtcfgName[0])); + if ( 0 == wmt_dev_patch_get(&gDevWmt.cWmtcfgName[0], (osal_firmware **)&gDevWmt.pWmtCfg, 0) ) + { + /*get full name patch success*/ + WMT_INFO_FUNC("get full file name(%s) buf(0x%p) size(%d)\n", + &gDevWmt.cWmtcfgName[0], gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size); + + if( 0 == wmt_conf_parse(&gDevWmt, (const PCHAR)gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size)) + { + /*config file exists*/ + gDevWmt.rWmtGenConf.cfgExist = 1; + + WMT_INFO_FUNC("&gDevWmt.rWmtGenConf=%p\n", &gDevWmt.rWmtGenConf); + ret = 0; + } + else + { + WMT_ERR_FUNC("wmt conf parsing fail\n"); + osal_assert(0); + ret = -1; + } + wmt_dev_patch_put((osal_firmware **)&gDevWmt.pWmtCfg); +/* + if (gDevWmt.pWmtCfg) + { + if (gDevWmt.pWmtCfg->data) + { + osal_free(gDevWmt.pWmtCfg->data); + } + osal_free(gDevWmt.pWmtCfg); + gDevWmt.pWmtCfg = 0; + } +*/ + return ret; + } + else + { + WMT_ERR_FUNC("read %s file fails\n", &(gDevWmt.cWmtcfgName[0])); + osal_assert(0); + + gDevWmt.rWmtGenConf.cfgExist = 0; + return ret; + } +} + +P_WMT_GEN_CONF wmt_conf_get_cfg(VOID) +{ + if (0 == gDevWmt.rWmtGenConf.cfgExist) + { + return NULL; + } + return &gDevWmt.rWmtGenConf; +} + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_core.c b/drivers/mtk_wcn_combo/common/core/wmt_core.c new file mode 100755 index 000000000000..d99ca6630168 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_core.c @@ -0,0 +1,2025 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CORE]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_lib.h" +#include "wmt_core.h" +#include "wmt_ctrl.h" +#include "wmt_ic.h" +#include "wmt_conf.h" + +#include "wmt_func.h" +#include "stp_core.h" +#include "psm_core.h" + +#if CFG_CORE_MT6620_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6620; +#endif + +#if CFG_CORE_MT6628_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6628; +#endif + +#if CFG_FUNC_BT_SUPPORT +extern WMT_FUNC_OPS wmt_func_bt_ops; +#endif + +#if CFG_FUNC_FM_SUPPORT +extern WMT_FUNC_OPS wmt_func_fm_ops; +#endif + +#if CFG_FUNC_GPS_SUPPORT +extern WMT_FUNC_OPS wmt_func_gps_ops; +#endif + +#if CFG_FUNC_WIFI_SUPPORT +extern WMT_FUNC_OPS wmt_func_wifi_ops; +#endif + +P_WMT_FUNC_OPS gpWmtFuncOps[4] = { +#if CFG_FUNC_BT_SUPPORT + [0] = &wmt_func_bt_ops, +#else + [0] = NULL, +#endif + +#if CFG_FUNC_FM_SUPPORT + [1] = &wmt_func_fm_ops, +#else + [1] = NULL, +#endif + +#if CFG_FUNC_GPS_SUPPORT + [2] = &wmt_func_gps_ops, +#else + [2] = NULL, +#endif + +#if CFG_FUNC_WIFI_SUPPORT + [3] = &wmt_func_wifi_ops, +#else + [3] = NULL, +#endif + +}; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +// TODO:[FixMe][GeorgeKuo]: is it an MT6620 only or general general setting? move to wmt_ic_6620 temporarily. +/* #define CFG_WMT_BT_PORT2 (1) */ /* BT Port 2 Feature.*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +static WMT_CTX gMtkWmtCtx; +static UINT8 gLpbkBuf[WMT_LPBK_BUF_LEN] = {0}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 opfunc_hif_conf (P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_on (P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_off (P_WMT_OP pWmtOp); +static INT32 opfunc_func_on (P_WMT_OP pWmtOp); +static INT32 opfunc_func_off (P_WMT_OP pWmtOp); +static INT32 opfunc_reg_rw ( P_WMT_OP pWmtOp); +static INT32 opfunc_exit (P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_sv (P_WMT_OP pWmtOp); +static INT32 opfunc_dsns (P_WMT_OP pWmtOp); +static INT32 opfunc_lpbk (P_WMT_OP pWmtOp); +static INT32 opfunc_cmd_test (P_WMT_OP pWmtOp); +static INT32 opfunc_hw_rst (P_WMT_OP pWmtOp); +static INT32 opfunc_sw_rst (P_WMT_OP pWmtOp); +static INT32 opfunc_stp_rst (P_WMT_OP pWmtOp); +static INT32 opfunc_therm_ctrl (P_WMT_OP pWmtOp); +static INT32 opfunc_efuse_rw (P_WMT_OP pWmtOp); +static INT32 opfunc_therm_ctrl (P_WMT_OP pWmtOp); +static INT32 opfunc_gpio_ctrl (P_WMT_OP pWmtOp); +static INT32 opfunc_sdio_ctrl (P_WMT_OP pWmtOp); +static INT32 opfunc_pin_state (P_WMT_OP pWmtOp); +static VOID wmt_core_dump_func_state (CHAR *pSource); +static INT32 wmt_core_stp_init (VOID); +static INT32 wmt_core_stp_deinit (VOID); +static INT32 wmt_core_hw_check (VOID); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +const static UCHAR WMT_SLEEP_CMD[] = {0x01, 0x03, 0x01, 0x00, 0x01}; +const static UCHAR WMT_SLEEP_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x01}; + +const static UCHAR WMT_HOST_AWAKE_CMD[] = {0x01, 0x03, 0x01, 0x00, 0x02}; +const static UCHAR WMT_HOST_AWAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x02}; + +const static UCHAR WMT_WAKEUP_CMD[] = {0xFF}; +const static UCHAR WMT_WAKEUP_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03}; + +static UCHAR WMT_THERM_CMD[] = {0x01, 0x11, 0x01, 0x00, + 0x00 /*thermal sensor operation*/ +}; +static UCHAR WMT_THERM_CTRL_EVT[] = {0x02, 0x11, 0x01, 0x00, 0x00}; +static UCHAR WMT_THERM_READ_EVT[] = {0x02, 0x11, 0x02, 0x00, 0x00, 0x00}; + +static UCHAR WMT_EFUSE_CMD[] = {0x01, 0x0D, 0x08, 0x00, + 0x01, /*[4]operation, 0:init, 1:write 2:read*/ + 0x01, /*[5]Number of register setting*/ + 0xAA, 0xAA, /*[6-7]Address*/ + 0xBB, 0xBB, 0xBB, 0xBB /*[8-11] Value*/ +}; + +static UCHAR WMT_EFUSE_EVT[] = {0x02, 0x0D, 0x08, 0x00, + 0xAA, /*[4]operation, 0:init, 1:write 2:read*/ + 0xBB, /*[5]Number of register setting*/ + 0xCC, 0xCC, /*[6-7]Address*/ + 0xDD, 0xDD, 0xDD, 0xDD /*[8-11] Value*/ +}; + +static UCHAR WMT_DSNS_CMD[] = {0x01, 0x0E, 0x02, 0x00, 0x01, + 0x00 /*desnse type*/ +}; +static UCHAR WMT_DSNS_EVT[] = {0x02, 0x0E, 0x01, 0x00, 0x00 }; + +// TODO:[NewFeature][GeorgeKuo] Update register group in ONE CMD/EVT +static UCHAR WMT_SET_REG_CMD[] = {0x01, 0x08, 0x10, 0x00 /*length*/ + , 0x00 /*op: w(1) & r(2) */ + , 0x01 /*type: reg */ + , 0x00 /*res*/ + , 0x01 /*1 register*/ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ + , 0xFF, 0xFF, 0xFF, 0xFF /*mask */ +}; +static UCHAR WMT_SET_REG_WR_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + , 0x00 /*S: 0*/ + , 0x00 /*type: reg */ + , 0x00 /*rev*/ + , 0x01 /*1 register*/ + //, 0x00, 0x00, 0x00, 0x00 /* addr */ + //, 0x00, 0x00, 0x00, 0x00 /* value */ +}; +static UCHAR WMT_SET_REG_RD_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + , 0x00 /*S: 0*/ + , 0x00 /*type: reg */ + , 0x00 /*rev*/ + , 0x01 /*1 register*/ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ +}; + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ + +const static WMT_OPID_FUNC wmt_core_opfunc[] = { + [WMT_OPID_HIF_CONF] = opfunc_hif_conf, + [WMT_OPID_PWR_ON] = opfunc_pwr_on, + [WMT_OPID_PWR_OFF] = opfunc_pwr_off, + [WMT_OPID_FUNC_ON] = opfunc_func_on, + [WMT_OPID_FUNC_OFF] = opfunc_func_off, + [WMT_OPID_REG_RW] = opfunc_reg_rw, // TODO:[ChangeFeature][George] is this OP obsoleted? + [WMT_OPID_EXIT] = opfunc_exit, + [WMT_OPID_PWR_SV] = opfunc_pwr_sv, + [WMT_OPID_DSNS] = opfunc_dsns, + [WMT_OPID_LPBK] = opfunc_lpbk, + [WMT_OPID_CMD_TEST] = opfunc_cmd_test, + [WMT_OPID_HW_RST] = opfunc_hw_rst, + [WMT_OPID_SW_RST] = opfunc_sw_rst, + [WMT_OPID_STP_RST] = opfunc_stp_rst, + [WMT_OPID_THERM_CTRL] = opfunc_therm_ctrl, + [WMT_OPID_EFUSE_RW] = opfunc_efuse_rw, + [WMT_OPID_GPIO_CTRL] = opfunc_gpio_ctrl, + [WMT_OPID_SDIO_CTRL] = opfunc_sdio_ctrl, + [WMT_OPID_GPIO_STATE] = opfunc_pin_state, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_core_init(VOID) +{ + INT32 i = 0; + + osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); + /* gMtkWmtCtx.p_ops is cleared to NULL */ + + /* default FUNC_OFF state */ + for (i = 0; i < WMTDRV_TYPE_MAX; ++i) { + /* WinMo is default to DRV_STS_UNREG;*/ + gMtkWmtCtx.eDrvStatus[i] = DRV_STS_POWER_OFF; + } + + return 0; +} + +INT32 wmt_core_deinit(VOID) +{ + //return to init state + osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); + /* gMtkWmtCtx.p_ops is cleared to NULL */ + return 0; +} + +// TODO: [ChangeFeature][George] Is wmt_ctrl a good interface? maybe not...... +// parameters shall be copied in/from ctrl buffer, which is also a size-wasting buffer. +INT32 +wmt_core_tx ( + const UINT8 *pData, + const UINT32 size, + UINT32 *writtenSize, + const MTK_WCN_BOOL bRawFlag + ) +{ + INT32 iRet; +#if 0 /* Test using direct function call instead of wmt_ctrl() interface */ + WMT_CTRL_DATA ctrlData; + ctrlData.ctrlId = WMT_CTRL_TX; + ctrlData.au4CtrlData[0] = (UINT32)pData; + ctrlData.au4CtrlData[1] = size; + ctrlData.au4CtrlData[2] = (UINT32)writtenSize; + ctrlData.au4CtrlData[3] = bRawFlag; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_TX, iRet:%d\n", iRet); + //(*sys_dbg_assert)(0, __FILE__, __LINE__); + osal_assert(0); + } +#endif + iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); + return iRet; +} + +INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, UINT32 *readSize) +{ + INT32 iRet; + WMT_CTRL_DATA ctrlData; + ctrlData.ctrlId = WMT_CTRL_RX; + ctrlData.au4CtrlData[0] = (UINT32)pBuf; + ctrlData.au4CtrlData[1] = bufLen; + ctrlData.au4CtrlData[2] = (UINT32)readSize; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX, iRet:%d\n", iRet); + mtk_wcn_stp_dbg_dump_package(); + osal_assert(0); + } + return iRet; +} + +INT32 wmt_core_rx_flush(UINT32 type) +{ + INT32 iRet; + WMT_CTRL_DATA ctrlData; + ctrlData.ctrlId = WMT_CTRL_RX_FLUSH; + ctrlData.au4CtrlData[0] = (UINT32)type; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX_FLUSH, iRet:%d\n", iRet); + osal_assert(0); + } + return iRet; +} + +INT32 wmt_core_func_ctrl_cmd ( + ENUM_WMTDRV_TYPE_T type, + MTK_WCN_BOOL fgEn + ) +{ + INT32 iRet = 0; + UINT32 u4WmtCmdPduLen; + UINT32 u4WmtEventPduLen; + UINT32 u4ReadSize; + UINT32 u4WrittenSize; + WMT_PKT rWmtPktCmd; + WMT_PKT rWmtPktEvent; + MTK_WCN_BOOL fgFail; + + // TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. + // Using this struct relies on compiler's implementation and pack() settings + osal_memset(&rWmtPktCmd, 0, osal_sizeof(rWmtPktCmd)); + osal_memset(&rWmtPktEvent, 0, osal_sizeof(rWmtPktEvent)); + + rWmtPktCmd.eType = (UINT8)PKT_TYPE_CMD; + rWmtPktCmd.eOpCode = (UINT8)OPCODE_FUNC_CTRL; + + // Flag field: driver type + rWmtPktCmd.aucParam[0] = (UINT8)type; + // Parameter field: ON/OFF + rWmtPktCmd.aucParam[1] = (fgEn == WMT_FUNC_CTRL_ON) ? 1 : 0; + rWmtPktCmd.u2SduLen = WMT_FLAG_LEN + WMT_FUNC_CTRL_PARAM_LEN; // (2) + + // WMT Header + WMT SDU + u4WmtCmdPduLen = WMT_HDR_LEN + rWmtPktCmd.u2SduLen; // (6) + u4WmtEventPduLen = WMT_HDR_LEN + WMT_STS_LEN; // (5) + + do { + fgFail = MTK_WCN_BOOL_TRUE; +// iRet = (*kal_stp_tx)((PUINT8)&rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize); + iRet = wmt_core_tx((PUINT8)&rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_tx failed \n"); + break; + } + + iRet = wmt_core_rx((PUINT8)&rWmtPktEvent, u4WmtEventPduLen, &u4ReadSize); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_rx failed\n"); + break; + } + + /* Error Checking */ + if (PKT_TYPE_EVENT != rWmtPktEvent.eType) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd PKT_TYPE_EVENT != rWmtPktEvent.eType %d\n", rWmtPktEvent.eType); + break; + } + + if (rWmtPktCmd.eOpCode != rWmtPktEvent.eOpCode) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd rWmtPktCmd.eOpCode(0x%x) != rWmtPktEvent.eType(0x%x)\n", + rWmtPktCmd.eOpCode, rWmtPktEvent.eOpCode); + break; + } + + if (u4WmtEventPduLen != (rWmtPktEvent.u2SduLen + WMT_HDR_LEN)) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd u4WmtEventPduLen(0x%x) != rWmtPktEvent.u2SduLen(0x%x)+4\n", + u4WmtEventPduLen, rWmtPktEvent.u2SduLen); + break; + } + + // Status field of event check + if (0 != rWmtPktEvent.aucParam[0]) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd, 0 != status(%d)\n", rWmtPktEvent.aucParam[0]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + } while (0); + + if (MTK_WCN_BOOL_FALSE == fgFail) { + //WMT_INFO_FUNC("WMT-CORE: wmt_func_ctrl_cmd OK!\n"); + return 0; + } + else { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd 0x%x FAIL\n", rWmtPktCmd.aucParam[0]); + return -2; + } +} + +INT32 wmt_core_opid_handler(P_WMT_OP pWmtOp) +{ + UINT32 opId; + INT32 ret; + + opId = pWmtOp->opId; + + if (wmt_core_opfunc[opId]) { + ret = (*(wmt_core_opfunc[opId]))(pWmtOp); /*wmtCoreOpidHandlerPack[].opHandler*/ + return ret; + } + else { + WMT_ERR_FUNC("WMT-CORE: null handler (%d)\n", pWmtOp->opId); + return -2; + } +} + +INT32 wmt_core_opid(P_WMT_OP pWmtOp) +{ + + /*sanity check*/ + if (NULL == pWmtOp) { + WMT_ERR_FUNC("null pWmtOP\n"); + /*print some message with error info*/ + return -1; + } + + if (WMT_OPID_MAX <= pWmtOp->opId) { + WMT_ERR_FUNC("WMT-CORE: invalid OPID(%d)\n", pWmtOp->opId); + return -2; + } + + // TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here + return wmt_core_opid_handler(pWmtOp); +} + +INT32 wmt_core_ctrl (ENUM_WMT_CTRL_T ctrId, PUINT32 pPa1, PUINT32 pPa2) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + UINT32 val1 = (pPa1) ? *pPa1: 0; + UINT32 val2 = (pPa2) ? *pPa2 : 0; + + ctrlData.ctrlId= (UINT32)ctrId; + ctrlData.au4CtrlData[0] = val1; + ctrlData.au4CtrlData[1] = val2; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: id(%d), type(%d), value(%d) iRet:(%d)\n", ctrId, val1, val2, iRet); + osal_assert(0); + } + else { + if (pPa1) { + *pPa1 = ctrlData.au4CtrlData[0]; + } + if (pPa2) { + *pPa2 = ctrlData.au4CtrlData[1]; + } + } + return iRet; +} + + +VOID wmt_core_dump_data ( + PUINT8 pData, + PUINT8 pTitle, + UINT32 len + ) +{ + PUINT8 ptr = pData; + INT32 k=0; + WMT_INFO_FUNC("%s len=%d\n", pTitle, len); + for(k=0; k < len ; k++) { + if (k % 16 == 0) WMT_INFO_FUNC("\n"); + WMT_INFO_FUNC("0x%02x ", *ptr); + ptr++; + } + WMT_INFO_FUNC("--end\n"); +} + +/*! + * \brief An WMT-CORE function to support read, write, and read after write to + * an internal register. + * + * Detailed description. + * + * \param isWrite 1 for write, 0 for read + * \param offset of register to be written or read + * \param pVal a pointer to the 32-bit value to be writtern or read + * \param mask a 32-bit mask to be applied for the read or write operation + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval -2 tx cmd fail + * \retval -3 rx event fail + * \retval -4 read check error + */ +INT32 +wmt_core_reg_rw_raw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pVal, + UINT32 mask + ) +{ + INT32 iRet; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = {0}; + + WMT_SET_REG_CMD[4] = (isWrite) ? 0x1 : 0x2; /* w:1, r:2 */ + osal_memcpy(&WMT_SET_REG_CMD[8], &offset, 4); /* offset */ + osal_memcpy(&WMT_SET_REG_CMD[12], pVal, 4); /* [2] is var addr */ + osal_memcpy(&WMT_SET_REG_CMD[16], &mask, 4); /* mask */ + + /* send command */ + iRet = wmt_core_tx(WMT_SET_REG_CMD, sizeof(WMT_SET_REG_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if ( (iRet) || (u4Res != sizeof(WMT_SET_REG_CMD)) ) { + WMT_ERR_FUNC("Tx REG_CMD fail!(%d) len (%d, %d) \n", iRet, u4Res, sizeof(WMT_SET_REG_CMD)); + return -2; + } + + /* receive event */ + evtLen = (isWrite) ? sizeof(WMT_SET_REG_WR_EVT) : sizeof(WMT_SET_REG_RD_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if ( (iRet) || (u4Res != evtLen) ) { + WMT_ERR_FUNC("Rx REG_EVT fail!(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + return -3; + } + + if (!isWrite) { + UINT32 rxEvtAddr; + UINT32 txCmdAddr; + osal_memcpy(&txCmdAddr, &WMT_SET_REG_CMD[8], 4); + osal_memcpy(&rxEvtAddr, &evtBuf[8], 4); + + /* check read result */ + if (txCmdAddr != rxEvtAddr) { + WMT_ERR_FUNC("Check read addr fail (0x%08x, 0x%08x)\n", rxEvtAddr, txCmdAddr); + return -4; + } + else { + WMT_DBG_FUNC("Check read addr(0x%08x) ok\n", rxEvtAddr); + } + osal_memcpy(pVal, &evtBuf[12], 4); + } + + /* no error here just return 0 */ + return 0; +} + +INT32 +wmt_core_init_script ( + struct init_script *script, + INT32 count + ) +{ + UCHAR evtBuf[256]; + UINT32 u4Res; + INT32 i = 0; + INT32 iRet; + + for (i = 0; i < count; i++) { + WMT_DBG_FUNC("WMT-CORE: init_script operation %s start \n", script[i].str); + /* CMD */ + //iRet = (*kal_stp_tx)(script[i].cmd, script[i].cmdSz, &u4Res); + iRet = wmt_core_tx(script[i].cmd, script[i].cmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != script[i].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d) \n", script[i].str, iRet, u4Res, script[i].cmdSz); + break; + } + /* EVENT BUF */ + osal_memset(evtBuf, 0, sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, script[i].evtSz, &u4Res); + if (iRet || (u4Res != script[i].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d) \n", script[i].str, iRet, u4Res, script[i].evtSz); + mtk_wcn_stp_dbg_dump_package(); + break; + } + /* RESULT */ + if (osal_memcmp(evtBuf, script[i].evt, script[i].evtSz) != 0) { + WMT_ERR_FUNC("WMT-CORE:compare %s result error \n", script[i].str); + WMT_ERR_FUNC("WMT-CORE:rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + script[i].evtSz, script[i].evt[0], script[i].evt[1], script[i].evt[2], script[i].evt[3], script[i].evt[4]); + mtk_wcn_stp_dbg_dump_package(); + break; + } + + WMT_DBG_FUNC("init_script operation %s ok \n", script[i].str); + } + + return (i == count) ? 0 : -1; +} + +static INT32 +wmt_core_stp_init (VOID) +{ + INT32 iRet = -1; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + P_WMT_CTX pctx = &gMtkWmtCtx; + P_WMT_GEN_CONF pWmtGenConf = NULL; + wmt_conf_read_file(); + pWmtGenConf = wmt_conf_get_cfg(); + if (!(pctx->wmtInfoBit & WMT_OP_HIF_BIT)) { + WMT_ERR_FUNC("WMT-CORE: no hif info!\n"); + osal_assert(0); + return -1; + } + + //4 <0> turn on SDIO2 for common SDIO + if (WMT_HIF_SDIO == pctx->wmtHifConf.hifType) { + ctrlPa1 = WMT_SDIO_SLOT_SDIO2; + ctrlPa2 = 1; /* turn on SDIO2 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn on SLOT_SDIO2 fail (%d)\n", iRet); + osal_assert(0); + + return -2; + } + pctx->eDrvStatus[WMTDRV_TYPE_SDIO2] = DRV_STS_FUNC_ON; + + ctrlPa1 = WMT_SDIO_FUNC_STP; + ctrlPa2 = 1; /* turn on STP driver */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn on SDIO_FUNC_STP func fail (%d)\n", iRet); + + /* check all sub-func and do power off */ + return -3; + } + } + + //4 <1> open stp + ctrlPa1 = 0; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -4; + } + + if (WMT_HIF_UART == pctx->wmtHifConf.hifType) { + ctrlPa1 = WMT_DEFAULT_BAUD_RATE; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: change host baudrate(%d) fails \n", pctx->wmtHifConf.au4HifConf[0]); + return -5; + } + } + //WMT_DBG_FUNC("WMT-CORE: change host baudrate(%d) ok \n", gMtkWmtCtx.wmtHifConf.au4HifConf[0]); + + //4 <1.5> disable and un-ready stp + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_RDY; ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + //4 <2> set mode and enable + if (WMT_HIF_UART == pctx->wmtHifConf.hifType) { + ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + } + else if (WMT_HIF_SDIO == pctx->wmtHifConf.hifType) { + ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_SDIO_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + } + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); + return -7; + } + + // TODO: [ChangeFeature][GeorgeKuo] can we apply raise UART baud rate firstly for ALL supported chips??? + + iRet = wmt_core_hw_check(); + if (iRet) { + WMT_ERR_FUNC("hw_check fail:%d\n", iRet); + return -8; + } + /* mtkWmtCtx.p_ic_ops is identified and checked ok */ + if ((NULL != pctx->p_ic_ops->co_clock_ctrl) && (pWmtGenConf != NULL)) + { + (*(pctx->p_ic_ops->co_clock_ctrl))(pWmtGenConf->co_clock_flag == 0 ? WMT_CO_CLOCK_DIS : WMT_CO_CLOCK_EN); + } + else + { + WMT_INFO_FUNC("pctx->p_ic_ops->co_clock_ctrl(0x%x), pWmtGenConf(0x%x)\n", pctx->p_ic_ops->co_clock_ctrl, pWmtGenConf); + } + osal_assert(NULL != pctx->p_ic_ops->sw_init); + if (NULL != pctx->p_ic_ops->sw_init) { + iRet = (*(pctx->p_ic_ops->sw_init))(&pctx->wmtHifConf); + } + else { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); + return -9; + } + if (iRet) { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init fail:%d\n", iRet); + return -10; + } + + //4 <10> set stp ready + ctrlPa1 = WMT_STP_CONF_RDY; ctrlPa2 = 1; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + return iRet; +} + +static INT32 wmt_core_stp_deinit (VOID) +{ + INT32 iRet; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + WMT_DBG_FUNC(" start\n"); + + if (NULL == gMtkWmtCtx.p_ic_ops) { + WMT_WARN_FUNC("gMtkWmtCtx.p_ic_ops is NULL\n"); + goto deinit_ic_ops_done; + } + if (NULL != gMtkWmtCtx.p_ic_ops->sw_deinit) { + iRet = (*(gMtkWmtCtx.p_ic_ops->sw_deinit))(&gMtkWmtCtx.wmtHifConf); + /* unbind WMT-IC */ + gMtkWmtCtx.p_ic_ops= NULL; + } + else { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); + } + +deinit_ic_ops_done: + + //4 <1> un-ready, disable, and close stp. + ctrlPa1 = WMT_STP_CONF_RDY; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = 0; ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + + //4 <1.1> turn off SDIO2 for common SDIO + if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) { + ctrlPa1 = WMT_SDIO_FUNC_STP; + ctrlPa2 = 0; /* turn off STP driver */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_WARN_FUNC("turn off SDIO_FUNC_STP fail (%d)\n", iRet); + /* Anyway, continue turning SDIO HW off */ + } + else { + WMT_INFO_FUNC("turn off SDIO_FUNC_STP ok \n"); + } + + ctrlPa1 = WMT_SDIO_SLOT_SDIO2; + ctrlPa2 = 0; /* turn off SDIO2 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_WARN_FUNC("turn off SDIO2 HW fail (%d)\n", iRet); + /* Anyway, continue turning STP SDIO to POWER OFF state*/ + } + else { + WMT_INFO_FUNC("turn off SDIO2 HW ok \n"); + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2] = DRV_STS_POWER_OFF; + } + + if (iRet) { + WMT_WARN_FUNC("end with fail:%d\n", iRet); + } + + return iRet; +} + +static VOID +wmt_core_dump_func_state ( + CHAR *pSource + ) +{ + WMT_INFO_FUNC("[%s]status(b:%d f:%d g:%d w:%d lpbk:%d coredump:%d wmt:%d sd1:%d sd2:%d stp:%d)\n", + (pSource == NULL ? (CHAR *)"CORE" : pSource), + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] + ); + return; + +} + +MTK_WCN_BOOL +wmt_core_patch_check ( + UINT32 u4PatchVer, + UINT32 u4HwVer + ) +{ + if (MAJORNUM(u4HwVer) != MAJORNUM(u4PatchVer)) { + /*major no. does not match*/ + WMT_ERR_FUNC("WMT-CORE: chip version(0x%d) does not match patch version(0x%d)\n", u4HwVer, u4PatchVer); + return MTK_WCN_BOOL_FALSE; + } + return MTK_WCN_BOOL_TRUE; +} + +static INT32 +wmt_core_hw_check (VOID) +{ + UINT32 chipid; + P_WMT_IC_OPS p_ops; + INT32 iret; + + // 1. get chip id + chipid = 0; + WMT_LOUD_FUNC("before read hwcode (chip id)\n"); + iret = wmt_core_reg_rw_raw(0, GEN_HCR, &chipid, GEN_HCR_MASK); /* read 0x80000008 */ + if (iret) { + WMT_ERR_FUNC("get hwcode (chip id) fail (%d)\n", iret); + return -2; + } + WMT_INFO_FUNC("get hwcode (chip id) (0x%x)\n", chipid); + + // TODO:[ChangeFeature][George]: use a better way to select a correct ops table based on chip id + switch (chipid) { +#if CFG_CORE_MT6620_SUPPORT + case 0x6620: + p_ops = &wmt_ic_ops_mt6620; + break; +#endif +#if CFG_CORE_MT6628_SUPPORT + case 0x6628: + p_ops = &wmt_ic_ops_mt6628; + break; +#endif + default: + p_ops = (P_WMT_IC_OPS)NULL; + break; + } + + if (NULL == p_ops) { + WMT_ERR_FUNC("unsupported chip id (hw_code): 0x%x\n", chipid); + return -3; + } + else if ( MTK_WCN_BOOL_FALSE == wmt_core_ic_ops_check(p_ops)) { + WMT_ERR_FUNC("chip id(0x%x) with null operation fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", + chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); + return -4; + } + WMT_DBG_FUNC("chip id(0x%x) fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", + chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); + + iret = p_ops->ic_ver_check(); + if (iret) { + WMT_ERR_FUNC("chip id(0x%x) ver_check error:%d\n", chipid, iret); + return -5; + } + + WMT_INFO_FUNC("chip id(0x%x) ver_check ok\n", chipid); + gMtkWmtCtx.p_ic_ops = p_ops; + return 0; +} + +static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp) +{ + if (!(pWmtOp->u4InfoBit & WMT_OP_HIF_BIT)) { + WMT_ERR_FUNC("WMT-CORE: no HIF_BIT in WMT_OP!\n"); + return -1; + } + + if (gMtkWmtCtx.wmtInfoBit & WMT_OP_HIF_BIT) { + WMT_ERR_FUNC("WMT-CORE: WMT HIF already exist. overwrite! old (%d), new(%d))\n", + gMtkWmtCtx.wmtHifConf.hifType, + pWmtOp->au4OpData[0]); + } + else { + gMtkWmtCtx.wmtInfoBit |= WMT_OP_HIF_BIT; + WMT_ERR_FUNC("WMT-CORE: WMT HIF info added\n"); + } + + osal_memcpy(&gMtkWmtCtx.wmtHifConf, + &pWmtOp->au4OpData[0], + osal_sizeof(gMtkWmtCtx.wmtHifConf)); + return 0; + +} + +static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + INT32 retry = WMT_PWRON_RTY_DFT; + + if (DRV_STS_POWER_OFF != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: already powered on, WMT DRV_STS_[0x%x]\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + + // TODO: [FixMe][GeorgeKuo]: clarify the following is reqiured or not! + if (pWmtOp->u4InfoBit & WMT_OP_HIF_BIT) { + opfunc_hif_conf(pWmtOp); + } + +pwr_on_rty: + /* power on control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); + if (0 == retry--) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + return -1; + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + + /* init stp */ + iRet = wmt_core_stp_init(); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_core_stp_init fail (%d)\n", iRet); + osal_assert(0); + + /* deinit stp */ + iRet = wmt_core_stp_deinit(); + iRet = opfunc_pwr_off(pWmtOp); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: opfunc_pwr_off fail during pwr_on retry\n"); + } + + if (0 < retry--) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + iRet = -2; + return iRet; + } + + WMT_DBG_FUNC("WMT-CORE: WMT [FUNC_ON]\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + + /* What to do when state is changed from POWER_OFF to POWER_ON? + * 1. STP driver does s/w reset + * 2. UART does 0xFF wake up + * 3. SDIO does re-init command(changed to trigger by host) + */ + return iRet; + +} + +static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_WARN_FUNC("WMT-CORE: WMT already off, WMT DRV_STS_[0x%x]\n", gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + + /* wmt and stp are initialized successfully */ + if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + iRet = wmt_core_stp_deinit(); + if (iRet) { + WMT_WARN_FUNC("wmt_core_stp_deinit fail (%d)\n", iRet); + /*should let run to power down chip*/ + } + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + + /* power off control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_OFF, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_WARN_FUNC("HW_PWR_OFF fail (%d)\n", iRet); + } + else { + WMT_WARN_FUNC("HW_PWR_OFF ok\n"); + } + + /*anyway, set to POWER_OFF state */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + return iRet; + +} + +static INT32 +opfunc_func_on ( + P_WMT_OP pWmtOp + ) +{ + INT32 iRet = -1; + INT32 iPwrOffRet = -1; + UINT32 drvType; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + drvType = pWmtOp->au4OpData[0]; + + /* Check abnormal type */ + if (WMTDRV_TYPE_COREDUMP < drvType) { + WMT_ERR_FUNC("abnormal Fun(%d)\n", + drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if ( (DRV_STS_POWER_OFF > gMtkWmtCtx.eDrvStatus[drvType]) + || (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType]) ) { + WMT_ERR_FUNC("func(%d) status[0x%x] abnormal\n", + drvType, + gMtkWmtCtx.eDrvStatus[drvType]); + osal_assert(0); + return -2; + } + + /* check if func already on */ + if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_WARN_FUNC("func(%d) already on\n", drvType); + return 0; + } + + /* check if chip power on is needed */ + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + iRet = opfunc_pwr_on(pWmtOp); + + if (iRet) { + WMT_ERR_FUNC("func(%d) pwr_on fail(%d)\n", drvType, iRet); + osal_assert(0); + + /* check all sub-func and do power off */ + return -3; + } + } + + if (WMTDRV_TYPE_WMT > drvType) { + if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_on) + { + + /* special handling for Wi-Fi */ + if (WMTDRV_TYPE_WIFI == drvType) { + if (WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) { + ctrlPa1 = WMT_SDIO_SLOT_SDIO1; + ctrlPa2 = 1; /* turn on SDIO1 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("turn on SLOT_SDIO1 fail (%d)\n", iRet); + osal_assert(0); + /* check all sub-func and do power off */ + } + else { + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_FUNC_ON; + } + } + else if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) { + if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]) { + WMT_DBG_FUNC("SLOT_SDIO2 ready for WIFI\n"); + } + else { + /* SDIO2 slot power shall be either turned on in STP init + * procedures already, or failed in STP init before. Here is + * the assert condition. + **/ + WMT_ERR_FUNC("WMT-CORE: turn on Wi-Fi in comm SDIO2 but SDIO in FUNC_OFF state(0x%x)\n", gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]); + osal_assert(0); + return -4; + } + } + else { + WMT_ERR_FUNC("WMT-CORE: error, not implemented yet gMtkWmtCtx.wmtHifConf.hifType: 0x%x, unspecified wifi_hif\n", gMtkWmtCtx.wmtHifConf.hifType); + // TODO: Wi-Fi/WMT uses other interfaces. NOT IMPLEMENTED YET! + } + + } + iRet = (*(gpWmtFuncOps[drvType]->func_on))(gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (0 != iRet) + { + if (WMTDRV_TYPE_WIFI == drvType && WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) { + /*need to power SDIO off when Power on Wi-Fi fail, in case of power leakage and right SDIO power status maintain*/ + ctrlPa1 = WMT_SDIO_SLOT_SDIO1; + ctrlPa2 = 0; /* turn off SDIO1 slot */ + wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + //does not need to check turn off result + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF; + + } + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + } + else + { + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + } + } + else + { + WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); + iRet = -5; + } + } + else + { + if (WMTDRV_TYPE_LPBK == drvType) { + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + } + else if (WMTDRV_TYPE_COREDUMP == drvType) { + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + }; + iRet = 0; + } + + if (iRet) { + WMT_ERR_FUNC("WMT-CORE:type(0x%x) function on failed, ret(%d)\n", drvType, iRet); + osal_assert(0); + //FIX-ME:[Chaozhong Liang], Error handling? check subsystem state and do pwr off if necessary? + /* check all sub-func and do power off */ + if ( (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { + WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); + + iPwrOffRet = opfunc_pwr_off(pWmtOp); + if (iPwrOffRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iPwrOffRet, drvType); + osal_assert(0); + } + } + return iRet; + } + + wmt_core_dump_func_state("AF FUNC ON"); + + return 0; +} + +static INT32 opfunc_func_off(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 drvType; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + drvType = pWmtOp->au4OpData[0]; + /* Check abnormal type */ + if (WMTDRV_TYPE_COREDUMP < drvType) { + WMT_ERR_FUNC("WMT-CORE: abnormal Fun(%d) in wmt_func_off \n", drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_ERR_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] abnormal in wmt_func_off \n", + drvType, + gMtkWmtCtx.eDrvStatus[drvType]); + osal_assert(0); + return -2; + } + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_WARN_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] already non-FUN_ON in wmt_func_off \n", + drvType, + gMtkWmtCtx.eDrvStatus[drvType]); + //needs to check 4 subsystem's state? + return 0; + }else if (WMTDRV_TYPE_WMT > drvType) { + if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_off) + { + iRet = (*(gpWmtFuncOps[drvType]->func_off))(gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + + if (WMTDRV_TYPE_WIFI == drvType && WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) { + UINT32 iRet = 0; + ctrlPa1 = WMT_SDIO_SLOT_SDIO1; + ctrlPa2 = 0; /* turn off SDIO1 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn on SLOT_SDIO1 fail (%d)\n", iRet); + osal_assert(0); + /* check all sub-func and do power off */ + } + //Anyway, turn SDIO1 state to POWER_OFF state + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF; + } + } + else + { + WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); + iRet = -3; + } + } else { + if (WMTDRV_TYPE_LPBK == drvType) { + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + }else if (WMTDRV_TYPE_COREDUMP == drvType) { + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + } + iRet = 0; + } + + //shall we put device state to POWER_OFF state when fail? + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: type(0x%x) function off failed, ret(%d)\n", drvType, iRet); + osal_assert(0); + //no matter subsystem function control fail or not, chip should be powered off when no subsystem is active + //return iRet; + } + + + /* check all sub-func and do power off */ + if ( (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { + WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); + + iRet = opfunc_pwr_off(pWmtOp); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iRet, drvType); + osal_assert(0); + } + } + + wmt_core_dump_func_state("AF FUNC OFF"); + return iRet; +} + +// TODO:[ChangeFeature][George] is this OP obsoleted? +static INT32 +opfunc_reg_rw ( + P_WMT_OP pWmtOp + ) +{ + INT32 iret; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("reg_rw when WMT is powered off\n"); + return -1; + } + iret = wmt_core_reg_rw_raw(pWmtOp->au4OpData[0], + pWmtOp->au4OpData[1], + (PUINT32)pWmtOp->au4OpData[2], + pWmtOp->au4OpData[3]); + + return iret; +} + +static INT32 +opfunc_exit ( + P_WMT_OP pWmtOp + ) +{ + // TODO: [FixMe][George] is ok to leave this function empty??? + WMT_WARN_FUNC("EMPTY FUNCTION\n"); + return 0; +} + +static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp) +{ + INT32 ret = -1; + UINT32 u4_result; + UINT32 evt_len; + UINT8 evt_buf[16] = {0}; + +typedef INT32 (*STP_PSM_CB)(INT32); + STP_PSM_CB psm_cb; + + if (SLEEP == pWmtOp->au4OpData[0]) { + WMT_DBG_FUNC("**** Send sleep command\n"); + //mtk_wcn_stp_set_psm_state(ACT_INACT); + //(*kal_stp_flush_rx)(WMT_TASK_INDX); + ret = wmt_core_tx(&WMT_SLEEP_CMD[0], sizeof(WMT_SLEEP_CMD), &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_SLEEP_CMD))) { + WMT_ERR_FUNC("wmt_core: SLEEP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, sizeof(WMT_SLEEP_CMD)); + goto pwr_sv_done; + } + + evt_len = sizeof(WMT_SLEEP_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) + { + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: read SLEEP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_SLEEP_EVT, sizeof(WMT_SLEEP_EVT)) != 0) + { + WMT_ERR_FUNC("wmt_core: compare WMT_SLEEP_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, evt_buf[0], evt_buf[1], evt_buf[2], evt_buf[3], evt_buf[4], evt_buf[5], + sizeof(WMT_SLEEP_EVT), WMT_SLEEP_EVT[0], WMT_SLEEP_EVT[1], + WMT_SLEEP_EVT[2], WMT_SLEEP_EVT[3], WMT_SLEEP_EVT[4], WMT_SLEEP_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } + else + { + WMT_INFO_FUNC("Send sleep command OK!\n"); + } + } + else if (pWmtOp->au4OpData[0] == WAKEUP) + { + WMT_DBG_FUNC("**** Send wakeup command\n"); + ret = wmt_core_tx(WMT_WAKEUP_CMD, sizeof(WMT_WAKEUP_CMD), &u4_result, 1); + + if (ret || (u4_result != sizeof(WMT_WAKEUP_CMD))) + { + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: WAKEUP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, sizeof(WMT_WAKEUP_CMD)); + goto pwr_sv_done; + } + + evt_len = sizeof(WMT_WAKEUP_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) + { + WMT_ERR_FUNC("wmt_core: read WAKEUP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_WAKEUP_EVT, sizeof(WMT_WAKEUP_EVT)) != 0) + { + WMT_ERR_FUNC("wmt_core: compare WMT_WAKEUP_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, evt_buf[0], evt_buf[1], evt_buf[2], evt_buf[3], evt_buf[4], evt_buf[5], + sizeof(WMT_WAKEUP_EVT), WMT_WAKEUP_EVT[0], WMT_WAKEUP_EVT[1], + WMT_WAKEUP_EVT[2], WMT_WAKEUP_EVT[3], WMT_WAKEUP_EVT[4], WMT_WAKEUP_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } + else + { + WMT_INFO_FUNC("Send wakeup command OK!\n"); + } + } else if (pWmtOp->au4OpData[0] == HOST_AWAKE){ + + WMT_DBG_FUNC("**** Send host awake command\n"); + + psm_cb = (STP_PSM_CB)pWmtOp->au4OpData[1]; + //(*kal_stp_flush_rx)(WMT_TASK_INDX); + ret = wmt_core_tx(WMT_HOST_AWAKE_CMD, sizeof(WMT_HOST_AWAKE_CMD), &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_HOST_AWAKE_CMD))) + { + WMT_ERR_FUNC("wmt_core: HOST_AWAKE_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, sizeof(WMT_HOST_AWAKE_CMD)); + goto pwr_sv_done; + } + + evt_len = sizeof(WMT_HOST_AWAKE_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) + { + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: read HOST_AWAKE_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_HOST_AWAKE_EVT, sizeof(WMT_HOST_AWAKE_EVT)) != 0) + { + WMT_ERR_FUNC("wmt_core: compare WMT_HOST_AWAKE_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, evt_buf[0], evt_buf[1], evt_buf[2], evt_buf[3], evt_buf[4], evt_buf[5], + sizeof(WMT_HOST_AWAKE_EVT), WMT_HOST_AWAKE_EVT[0], WMT_HOST_AWAKE_EVT[1], + WMT_HOST_AWAKE_EVT[2], WMT_HOST_AWAKE_EVT[3], WMT_HOST_AWAKE_EVT[4], WMT_HOST_AWAKE_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + //goto pwr_sv_done; + } + else + { + WMT_INFO_FUNC("Send host awake command OK!\n"); + } + } +pwr_sv_done: + + if (pWmtOp->au4OpData[0] < STP_PSM_MAX_ACTION) { + psm_cb = (STP_PSM_CB)pWmtOp->au4OpData[1]; + WMT_DBG_FUNC("Do STP-CB! %d %p\n", pWmtOp->au4OpData[0], (PVOID)pWmtOp->au4OpData[1]); + if (NULL != psm_cb) { + psm_cb(pWmtOp->au4OpData[0]); + } + else { + WMT_ERR_FUNC("fatal error !!!, psm_cb = %p, god, someone must have corrupted our memory.\n", psm_cb); + } + } + + return ret; +} + +static INT32 opfunc_dsns(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = {0}; + + WMT_DSNS_CMD[4] = pWmtOp->au4OpData[0]; + WMT_DSNS_CMD[5] = pWmtOp->au4OpData[1]; + + /* send command*/ + //iRet = (*kal_stp_tx)(WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res); + iRet = wmt_core_tx((PUINT8)WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_DSNS_CMD))) { + WMT_ERR_FUNC("WMT-CORE: DSNS_CMD iRet(%d) cmd len err(%d, %d) \n", iRet, u4Res, osal_sizeof(WMT_DSNS_CMD)); + return iRet; + } + + evtLen = osal_sizeof(WMT_DSNS_EVT); + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read DSNS_EVT fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + mtk_wcn_stp_dbg_dump_package(); + return iRet; + } + + if (osal_memcmp(evtBuf, WMT_DSNS_EVT, osal_sizeof(WMT_DSNS_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_DSNS_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + osal_sizeof(WMT_DSNS_EVT), WMT_DSNS_EVT[0], WMT_DSNS_EVT[1], WMT_DSNS_EVT[2], WMT_DSNS_EVT[3], WMT_DSNS_EVT[4]); + } else { + WMT_INFO_FUNC("Send WMT_DSNS_CMD command OK!\n"); + } + + return iRet; +} + + +static INT32 opfunc_lpbk(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT32 buf_length = 0; + UINT32 *pbuffer = NULL; + UINT16 len_in_cmd; + //UINT32 offset; + UINT8 WMT_TEST_LPBK_CMD[] = {0x1, 0x2, 0x0, 0x0, 0x7}; + UINT8 WMT_TEST_LPBK_EVT[] = {0x2, 0x2, 0x0, 0x0, 0x0}; + + //UINT8 lpbk_buf[1024 + 5] = {0}; + MTK_WCN_BOOL fgFail; + buf_length = pWmtOp->au4OpData[0]; //packet length + pbuffer = (VOID *)pWmtOp->au4OpData[1]; //packet buffer pointer + WMT_DBG_FUNC("WMT-CORE: -->wmt_do_lpbk \n"); + /*check if WMTDRV_TYPE_LPBK function is already on */ + if (DRV_STS_FUNC_ON!= gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] || buf_length + osal_sizeof(WMT_TEST_LPBK_CMD) > osal_sizeof(gLpbkBuf)) { + WMT_ERR_FUNC("WMT-CORE: abnormal LPBK in wmt_do_lpbk\n"); + osal_assert(0); + return -2; + } + /*package loopback for STP*/ + + // init buffer + osal_memset(gLpbkBuf, 0, osal_sizeof(gLpbkBuf)); + + len_in_cmd = buf_length + 1; /* add flag field */ + + osal_memcpy(&WMT_TEST_LPBK_CMD[2], &len_in_cmd, 2); + osal_memcpy(&WMT_TEST_LPBK_EVT[2], &len_in_cmd, 2); + + // wmt cmd + osal_memcpy(gLpbkBuf, WMT_TEST_LPBK_CMD, osal_sizeof(WMT_TEST_LPBK_CMD)); + osal_memcpy(gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), pbuffer, buf_length); + + do { + fgFail = MTK_WCN_BOOL_TRUE; + /*send packet through STP*/ + + //iRet = (*kal_stp_tx)((PUINT8)gLpbkBuf, osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length, &u4WrittenSize); + iRet = wmt_core_tx((PUINT8)gLpbkBuf, (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length), &u4WrittenSize, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("opfunc_lpbk wmt_core_tx failed \n"); + break; + } + /*receive firmware response from STP*/ + iRet = wmt_core_rx((PUINT8)gLpbkBuf, (osal_sizeof(WMT_TEST_LPBK_EVT) + buf_length), &u4ReadSize); + if (iRet) { + WMT_ERR_FUNC("opfunc_lpbk wmt_core_rx failed \n"); + break; + } + /*check if loopback response ok or not*/ + if (u4ReadSize != (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)) { + WMT_ERR_FUNC("lpbk event read size wrong(%d, %d) \n", u4ReadSize, (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)); + break; + } + if (osal_memcmp(WMT_TEST_LPBK_EVT, gLpbkBuf, osal_sizeof(WMT_TEST_LPBK_EVT))) { + WMT_ERR_FUNC("WMT-CORE WMT_TEST_LPBK_EVT error! read len %d [%02x,%02x,%02x,%02x,%02x] \n", + (INT32)u4ReadSize, + gLpbkBuf[0], gLpbkBuf[1], gLpbkBuf[2], gLpbkBuf[3], gLpbkBuf[4] + ); + break; + } + pWmtOp->au4OpData[0] = u4ReadSize - osal_sizeof(WMT_TEST_LPBK_EVT); + osal_memcpy((VOID *)pWmtOp->au4OpData[1], gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), buf_length); + fgFail = MTK_WCN_BOOL_FALSE; + }while(0); + /*return result*/ + //WMT_DBG_FUNC("WMT-CORE: <--wmt_do_lpbk, fgFail = %d \n", fgFail); + return fgFail; + +} + +static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp) +{ + + INT32 iRet = 0; + UINT32 cmdNo = 0; + UINT32 cmdNoPa = 0; + + UINT8 tstCmd[64]; + UINT8 tstEvt[64]; + UINT8 tstEvtTmp[64]; + UINT32 u4Res; + UINT32 tstCmdSz = 0; + UINT32 tstEvtSz = 0; + + UINT8 *pRes = NULL; + UINT32 resBufRoom = 0; + /*test command list*/ + /*1*/ + UINT8 WMT_ASSERT_CMD[] = {0x01, 0x02, 0x01, 0x00, 0x08}; + UINT8 WMT_ASSERT_EVT[] = {0x02, 0x02, 0x00, 0x00, 0x00}; + UINT8 WMT_EXCEPTION_CMD[] = {0x01, 0x02, 0x01, 0x00, 0x09}; + UINT8 WMT_EXCEPTION_EVT[] = {0x02, 0x02, 0x00, 0x00, 0x00}; + /*2*/ + UINT8 WMT_COEXDBG_CMD[] = {0x01,0x10,0x02,0x00, + 0x08, + 0xAA /*Debugging Parameter*/ + }; + UINT8 WMT_COEXDBG_1_EVT[] = {0x02,0x10,0x05,0x00, + 0x00, + 0xAA,0xAA,0xAA,0xAA /*event content*/ + }; + UINT8 WMT_COEXDBG_2_EVT[] = {0x02,0x10,0x07,0x00, + 0x00, + 0xAA,0xAA,0xAA,0xAA,0xBB,0xBB /*event content*/ + }; + UINT8 WMT_COEXDBG_3_EVT[] = {0x02,0x10,0x0B,0x00, + 0x00, + 0xAA,0xAA,0xAA,0xAA,0xBB,0xBB,0xBB,0xBB /*event content*/ + }; + /*test command list -end*/ + + cmdNo = pWmtOp->au4OpData[0]; + + WMT_INFO_FUNC("Send Test command %d!\n", cmdNo); + if (cmdNo == 0) { + /*dead command*/ + WMT_INFO_FUNC("Send Assert command !\n"); + tstCmdSz = osal_sizeof(WMT_ASSERT_CMD); + tstEvtSz = osal_sizeof(WMT_ASSERT_EVT); + osal_memcpy(tstCmd, WMT_ASSERT_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_ASSERT_EVT, tstEvtSz); + } else if (cmdNo == 1) { + /*dead command*/ + WMT_INFO_FUNC("Send Exception command !\n"); + tstCmdSz = osal_sizeof(WMT_EXCEPTION_CMD); + tstEvtSz = osal_sizeof(WMT_EXCEPTION_EVT); + osal_memcpy(tstCmd, WMT_EXCEPTION_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_EXCEPTION_EVT, tstEvtSz); + } else if (cmdNo == 2) { + cmdNoPa = pWmtOp->au4OpData[1]; + pRes = (UINT8 *)pWmtOp->au4OpData[2]; + resBufRoom = pWmtOp->au4OpData[3]; + if ((cmdNoPa >= 0x0) && (cmdNoPa <= 0xf)) { + WMT_INFO_FUNC("Send Coexistence Debug command [0x%x]!\n", cmdNoPa); + tstCmdSz = osal_sizeof(WMT_COEXDBG_CMD); + osal_memcpy(tstCmd, WMT_COEXDBG_CMD, tstCmdSz); + if (tstCmdSz > 5) { + tstCmd[5] = cmdNoPa; + } + + /*setup the expected event length*/ + if (cmdNoPa >= 0x0 && cmdNoPa <= 0x4) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_1_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_1_EVT, tstEvtSz); + }else if (cmdNoPa == 0x5) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_2_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_2_EVT, tstEvtSz); + }else if (cmdNoPa >= 0x6 && cmdNoPa <= 0xf) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_3_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_3_EVT, tstEvtSz); + } + else{ + + } + }else{ + WMT_ERR_FUNC("cmdNoPa is wrong\n"); + return iRet; + } + } else { + /*Placed youer test WMT command here, easiler to integrate and test with F/W side*/ + } + + /* send command*/ + //iRet = (*kal_stp_tx)(tstCmd, tstCmdSz, &u4Res); + iRet = wmt_core_tx((PUINT8)tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != tstCmdSz)) { + WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d) \n", iRet, u4Res, tstCmdSz); + return -1; + } + + if ((cmdNo == 0) || (cmdNo == 1)) { + WMT_INFO_FUNC("WMT-CORE: not to rx event for assert command\n"); + return 0; + } + + iRet = wmt_core_rx(tstEvtTmp, tstEvtSz, &u4Res); + + /*Event Post Handling*/ + if (cmdNo == 2) { + WMT_INFO_FUNC("#=========================================================#\n"); + WMT_INFO_FUNC("coext debugging id = %d", cmdNoPa); + if (tstEvtSz > 5) { + wmt_core_dump_data(&tstEvtTmp[5], "coex debugging ", tstEvtSz - 5); + }else { + WMT_ERR_FUNC("error coex debugging event\n"); + } + /*put response to buffer for shell to read*/ + if (pRes != NULL && resBufRoom > 0) + { + pWmtOp->au4OpData[3] = resBufRoom < tstEvtSz - 5 ? resBufRoom : tstEvtSz - 5; + osal_memcpy(pRes, &tstEvtTmp[5], pWmtOp->au4OpData[3]); + } + else + { + pWmtOp->au4OpData[3] = 0; + } + WMT_INFO_FUNC("#=========================================================#\n"); + } + + return iRet; + +} + +static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + wmt_core_dump_func_state("BE HW RST"); + /*-->Reset WMT data structure*/ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS] = DRV_STS_POWER_OFF; + //gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] = DRV_STS_POWER_OFF; + //gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1]= DRV_STS_POWER_OFF; + //gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]= DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] = DRV_STS_POWER_OFF; + + /* if wmt is poweroff, we need poweron chip first*/ + if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_WARN_FUNC("WMT-CORE: WMT is off, need re-poweron\n"); + /* power on control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); + return -1; + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + } + + /*--> reset SDIO fucntion/slot additionally if wifi ON*/ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] == DRV_STS_FUNC_ON) { + ctrlPa1 = WMT_SDIO_FUNC_WIFI; + ctrlPa2 = 0; /* turn off Wi-Fi driver */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off SDIO_WIFI func fail (%d)\n", iRet); + + /* check all sub-func and do power off */ + } else { + WMT_INFO_FUNC("wmt core: turn off SDIO WIFI func ok!!\n"); + } + //Anyway, turn off Wi-Fi Function + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; + + if (WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) { + ctrlPa1 = WMT_SDIO_SLOT_SDIO1; + ctrlPa2 = 0; /* turn off SDIO1 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off SLOT_SDIO1 fail (%d)\n", iRet); + osal_assert(0); + + /* check all sub-func and do power off */ + } else { + WMT_INFO_FUNC("WMT-CORE: turn off SLOT_SDIO1 successfully (%d)\n", iRet); + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF; + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; + } + + if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) { + ctrlPa1 = WMT_SDIO_FUNC_STP; + ctrlPa2 = 0; /* turn off STP driver */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off SDIO_FUNC_STP func fail (%d)\n", iRet); + + /* check all sub-func and do power off */ + //goto stp_deinit_done; + } else { + WMT_INFO_FUNC("WMT-CORE: turn off SDIO_FUNC_STP func successfully (%d)\n", iRet); + } + + ctrlPa1 = WMT_SDIO_SLOT_SDIO2; + ctrlPa2 = 0; /* turn off SDIO2 slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off SLOT_SDIO2 fail (%d)\n", iRet); + osal_assert(0); + + /* check all sub-func and do power off */ + //goto stp_deinit_done; + } else { + WMT_INFO_FUNC("WMT-CORE: turn off SLOT_SDIO2 successfully (%d)\n", iRet); + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2] = DRV_STS_POWER_OFF; + } +#if 0 + /*<4>Power off Combo chip*/ + ctrlPa1 = 0; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF fail (%d)", iRet); + } else { + WMT_INFO_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF ok (%d)", iRet); + } +#endif + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + + /*-->PesetCombo chip*/ + iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: -->[HW RST] fail iRet(%d)\n", iRet); + } else { + WMT_INFO_FUNC("WMT-CORE: -->[HW RST] ok\n"); + } + + //4 close stp + ctrlPa1 = 0; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt close stp failed\n"); + return -1; + } + + wmt_core_dump_func_state("AF HW RST"); + return iRet; + +} + +static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp) +{ +#if 0 + UINT32 iRet = -1; + if (NULL != gMtkWmtCtx.p_ic_ops->swInit) + { + iRet = (*(gMtkWmtCtx.p_ic_ops->swInit))(&gMtkWmtCtx.wmtHifConf); + } + else + { + WMT_ERR_FUNC("WMT-CORE: error, gMtkWmtCtx.p_ic_ops->swInit(NULL)\n"); + return -1; + } + if (0 == iRet) + { + WMT_ERR_FUNC("WMT-CORE: WMT-->[FUNC_ON] succeed\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + return 0; + } + return -2; +#endif + + return wmt_core_stp_init(); +} + +static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp) +{ + + return 0; +} + +static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = {0}; + + WMT_THERM_CMD[4] = pWmtOp->au4OpData[0];/*CMD type, refer to ENUM_WMTTHERM_TYPE_T*/ + + /* send command*/ + //iRet = (*kal_stp_tx)(WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res); + iRet = wmt_core_tx((PUINT8)WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_THERM_CMD))) { + WMT_ERR_FUNC("WMT-CORE: THERM_CTRL_CMD iRet(%d) cmd len err(%d, %d) \n", iRet, u4Res, osal_sizeof(WMT_THERM_CMD)); + return iRet; + } + + evtLen = 16; + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || ((u4Res != osal_sizeof(WMT_THERM_CTRL_EVT)) && (u4Res != osal_sizeof(WMT_THERM_READ_EVT) ))) { + WMT_ERR_FUNC("WMT-CORE: read THERM_CTRL_EVT/THERM_READ_EVENT fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + mtk_wcn_stp_dbg_dump_package(); + return iRet; + } + if (u4Res == osal_sizeof(WMT_THERM_CTRL_EVT)) + { + if (osal_memcmp(evtBuf, WMT_THERM_CTRL_EVT, osal_sizeof(WMT_THERM_CTRL_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_CTRL_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3],evtBuf[4], + osal_sizeof(WMT_THERM_CTRL_EVT), WMT_THERM_CTRL_EVT[0], WMT_THERM_CTRL_EVT[1], WMT_THERM_CTRL_EVT[2], WMT_THERM_CTRL_EVT[3], WMT_THERM_CTRL_EVT[4]); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_FALSE;/*will return to function driver*/ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_INFO_FUNC("Send WMT_THERM_CTRL_CMD command OK!\n"); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_TRUE;/*will return to function driver*/ + } + } + else + { + /*no need to judge the real thermal value*/ + if (osal_memcmp(evtBuf, WMT_THERM_READ_EVT, osal_sizeof(WMT_THERM_READ_EVT) - 1) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_READ_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3],evtBuf[4],evtBuf[5], + osal_sizeof(WMT_THERM_READ_EVT), WMT_THERM_READ_EVT[0], WMT_THERM_READ_EVT[1], WMT_THERM_READ_EVT[2], WMT_THERM_READ_EVT[3]); + pWmtOp->au4OpData[1] = 0xFF; /*will return to function driver*/ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_INFO_FUNC("Send WMT_THERM_READ_CMD command OK!\n"); + pWmtOp->au4OpData[1] = evtBuf[5];/*will return to function driver*/ + } + } + + return iRet; + +} + +static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = {0}; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: wmt_efuse_rw fail: chip is powered off\n"); + return -1; + } + + WMT_EFUSE_CMD[4] = (pWmtOp->au4OpData[0]) ? 0x1 : 0x2; /* w:2, r:1 */ + osal_memcpy(&WMT_EFUSE_CMD[6], (PUINT8)&pWmtOp->au4OpData[1], 2); /* address */ + osal_memcpy(&WMT_EFUSE_CMD[8], (PUINT32)pWmtOp->au4OpData[2], 4); /* value */ + + wmt_core_dump_data(&WMT_EFUSE_CMD[0], "efuse_cmd", osal_sizeof(WMT_EFUSE_CMD)); + + /* send command*/ + //iRet = (*kal_stp_tx)(WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res); + iRet = wmt_core_tx((PUINT8)WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_EFUSE_CMD))) { + WMT_ERR_FUNC("WMT-CORE: EFUSE_CMD iRet(%d) cmd len err(%d, %d) \n", iRet, u4Res, osal_sizeof(WMT_EFUSE_CMD)); + return iRet; + } + + evtLen = (pWmtOp->au4OpData[0]) ? osal_sizeof(WMT_EFUSE_EVT) : osal_sizeof(WMT_EFUSE_EVT); + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read REG_EVB fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + } + wmt_core_dump_data(&evtBuf[0], "efuse_evt", osal_sizeof(evtBuf)); + + return iRet; + +} + +static INT32 opfunc_gpio_ctrl (P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + WMT_IC_PIN_ID id; + WMT_IC_PIN_STATE stat; + UINT32 flag; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: wmt_gpio_ctrl fail: chip is powered off\n"); + return -1; + } + + if (!gMtkWmtCtx.p_ic_ops->ic_pin_ctrl) { + WMT_ERR_FUNC("WMT-CORE: error, gMtkWmtCtx.p_ic_ops->ic_pin_ctrl(NULL)\n"); + return -1; + } + + id = pWmtOp->au4OpData[0]; + stat = pWmtOp->au4OpData[1]; + flag = pWmtOp->au4OpData[2]; + + WMT_INFO_FUNC("ic pin id:%d, stat:%d, flag:0x%x\n", id , stat, flag); + + iRet = (*(gMtkWmtCtx.p_ic_ops->ic_pin_ctrl))(id , stat, flag); + + return iRet; +} + +//turn on/off sdio function +INT32 opfunc_sdio_ctrl (P_WMT_OP pWmtOp) +{ + UINT32 ctrlPa1 = 0; + UINT32 ctrlPa2 = 0; + UINT32 iRet = 0; + ctrlPa1 = WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType ? WMT_SDIO_SLOT_SDIO2 : WMT_SDIO_SLOT_SDIO1; + ctrlPa2 = pWmtOp->au4OpData[0]; /* turn off/on SDIO slot */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_WARN_FUNC("SDIO hw ctrl fail ret(%d)\n", iRet); + /* Anyway, continue turning STP SDIO to POWER OFF/ON state*/ + gMtkWmtCtx.eDrvStatus[ctrlPa1] = DRV_STS_POWER_OFF; + } + else { + WMT_INFO_FUNC("SDIO hw ctrl succeed \n"); + gMtkWmtCtx.eDrvStatus[ctrlPa1] = 0 ==ctrlPa2 ? DRV_STS_POWER_OFF : DRV_STS_POWER_ON; + } + + return 0; + +} + + +MTK_WCN_BOOL wmt_core_is_quick_ps_support (void) +{ + P_WMT_CTX pctx = &gMtkWmtCtx; + if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_quick_sleep)) + { + return (*(pctx->p_ic_ops->is_quick_sleep))(); + } + return MTK_WCN_BOOL_FALSE; +} + +MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_WMT_CTX pctx = &gMtkWmtCtx; + + if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_aee_dump_support)) + { + bRet = (*(pctx->p_ic_ops->is_aee_dump_support))(); + } + else + { + bRet = MTK_WCN_BOOL_FALSE; + } + + return bRet; +} + + +INT32 opfunc_pin_state (P_WMT_OP pWmtOp) +{ + + UINT32 ctrlPa1 = 0; + UINT32 ctrlPa2 = 0; + UINT32 iRet = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_STATE_DUMP, &ctrlPa1, &ctrlPa2) ; + return iRet; +} + + + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ctrl.c b/drivers/mtk_wcn_combo/common/core/wmt_ctrl.c new file mode 100755 index 000000000000..eff9b464a68a --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_ctrl.c @@ -0,0 +1,946 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CTRL]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "osal.h" + +#include "wmt_ctrl.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "wmt_dev.h" +#include "wmt_plat.h" +#include "hif_sdio.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +// moved to wmt_ctrl.h +/*static INT32 wmt_ctrl_tx_ex (UINT8 *pData, UINT32 size, UINT32 *writtenSize, MTK_WCN_BOOL bRawFlag);*/ + +static INT32 wmt_ctrl_stp_conf_ex (WMT_STP_CONF_TYPE type, UINT32 value); + +static INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_hwidver_set (P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_others(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData); +INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA); +static INT32 +wmt_ctrl_rx_flush ( + P_WMT_CTRL_DATA + ); + +static INT32 +wmt_ctrl_gps_sync_set ( + P_WMT_CTRL_DATA pData + ); + +static INT32 +wmt_ctrl_gps_lna_set ( + P_WMT_CTRL_DATA pData + ); + + +static INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData); + +// TODO: [FixMe][GeorgeKuo]: remove unused function +/*static INT32 wmt_ctrl_hwver_get(P_WMT_CTRL_DATA);*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +// TODO:[FixMe][GeorgeKuo]: use module APIs instead of direct access to internal data +extern DEV_WMT gDevWmt; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ +const static WMT_CTRL_FUNC wmt_ctrl_func[] = +{ + [WMT_CTRL_HW_PWR_OFF] = wmt_ctrl_hw_pwr_off, + [WMT_CTRL_HW_PWR_ON] = wmt_ctrl_hw_pwr_on, + [WMT_CTRL_HW_RST] = wmt_ctrl_hw_rst, + [WMT_CTRL_STP_CLOSE] = wmt_ctrl_stp_close, + [WMT_CTRL_STP_OPEN] = wmt_ctrl_stp_open, + [WMT_CTRL_STP_CONF] = wmt_ctrl_stp_conf, + [WMT_CTRL_FREE_PATCH] = wmt_ctrl_free_patch, + [WMT_CTRL_GET_PATCH] = wmt_ctrl_get_patch, + [WMT_CTRL_GET_PATCH_NAME] = wmt_ctrl_get_patch_name, + [WMT_CTRL_HOST_BAUDRATE_SET] = wmt_ctrl_host_baudrate_set, + [WMT_CTRL_SDIO_HW] = wmt_ctrl_sdio_hw, + [WMT_CTRL_SDIO_FUNC] = wmt_ctrl_sdio_func, + [WMT_CTRL_HWIDVER_SET] = wmt_ctrl_hwidver_set, + [WMT_CTRL_HWVER_GET] = NULL, // TODO: [FixMe][GeorgeKuo]: remove unused function. + [WMT_CTRL_STP_RST] = wmt_ctrl_stp_rst, + [WMT_CTRL_GET_WMT_CONF] = wmt_ctrl_get_wmt_conf, + [WMT_CTRL_TX] = wmt_ctrl_tx, + [WMT_CTRL_RX] = wmt_ctrl_rx, + [WMT_CTRL_RX_FLUSH] = wmt_ctrl_rx_flush, + [WMT_CTRL_GPS_SYNC_SET] = wmt_ctrl_gps_sync_set, + [WMT_CTRL_GPS_LNA_SET] = wmt_ctrl_gps_lna_set, + [WMT_CTRL_PATCH_SEARCH] = wmt_ctrl_patch_search, + [WMT_CTRL_CRYSTAL_TRIMING_GET] = wmt_ctrl_crystal_triming_get, + [WMT_CTRL_CRYSTAL_TRIMING_PUT] = wmt_ctrl_crystal_triming_put, + [WMT_CTRL_HW_STATE_DUMP] = wmt_ctrl_hw_state_show, + [WMT_CTRL_GET_PATCH_NUM] = wmt_ctrl_get_patch_num, + [WMT_CTRL_GET_PATCH_INFO] = wmt_ctrl_get_patch_info, + [WMT_CTRL_MAX] = wmt_ctrl_others, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 wmt_ctrl (P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 ctrlId = pWmtCtrlData->ctrlId; + + if (NULL == pWmtCtrlData) { + osal_assert(0); + return -1; + } + + /*1sanity check, including wmtCtrlId*/ + if ( (NULL == pWmtCtrlData) + || (WMT_CTRL_MAX <= ctrlId) ) + /* || (ctrlId < WMT_CTRL_HW_PWR_OFF) ) [FixMe][GeorgeKuo]: useless comparison */ + { + osal_assert(NULL != pWmtCtrlData); + osal_assert(WMT_CTRL_MAX > ctrlId); + /* osal_assert(ctrlId >= WMT_CTRL_HW_PWR_OFF); [FixMe][GeorgeKuo]: useless comparison */ + return -2; + } + + // TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here + if (wmt_ctrl_func[ctrlId]) { + /*call servicd handling API*/ + return (*(wmt_ctrl_func[ctrlId]))(pWmtCtrlData); /* serviceHandlerPack[ctrlId].serviceHandler */ + } + else { + osal_assert(NULL != wmt_ctrl_func[ctrlId]); + return -3; + } +} + +INT32 wmt_ctrl_tx (P_WMT_CTRL_DATA pWmtCtrlData/*UINT8 *pData, UINT32 size, UINT32 *writtenSize*/) +{ + UINT8 *pData = (UINT8 *)pWmtCtrlData->au4CtrlData[0]; + UINT32 size = pWmtCtrlData->au4CtrlData[1]; + UINT32 *writtenSize = (UINT32 *)pWmtCtrlData->au4CtrlData[2]; + MTK_WCN_BOOL bRawFlag = pWmtCtrlData->au4CtrlData[3]; + + return wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); +} + + +INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA pWmtCtrlData/*UINT8 *pBuff, UINT32 buffLen, UINT32 *readSize*/) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 readLen; + LONG waitRet = -1; + UINT8 *pBuff = (UINT8 *)pWmtCtrlData->au4CtrlData[0]; + UINT32 buffLen = pWmtCtrlData->au4CtrlData[1]; + UINT32 *readSize = (UINT32 *)pWmtCtrlData->au4CtrlData[2]; + + if (readSize) { + *readSize = 0; + } + + /* sanity check */ + if (!buffLen ) { + WMT_WARN_FUNC("buffLen = 0\n"); + osal_assert(buffLen); + return 0; + } + +#if 0 + if (!pDev) { + WMT_WARN_FUNC("gpDevWmt = NULL\n"); + osal_assert(pDev); + return -1; + } +#endif + + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { + WMT_WARN_FUNC("state(0x%lx) \n", pDev->state); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + return -2; + } + + /* sanity ok, proceeding rx operation */ + /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + + while (readLen == 0) { // got nothing, wait for STP's signal + WMT_LOUD_FUNC("before wmt_dev_rx_timeout\n"); + //iRet = wait_event_interruptible(pdev->rWmtRxWq, osal_test_bit(WMT_STAT_RX, &pdev->state)); + //waitRet = wait_event_interruptible_timeout(pDev->rWmtRxWq, osal_test_bit(WMT_STAT_RX, &pdev->state), msecs_to_jiffies(WMT_LIB_RX_TIMEOUT)); + pDev->rWmtRxWq.timeoutValue = WMT_LIB_RX_TIMEOUT; + //waitRet = osal_wait_for_event_bit_timeout(&pDev->rWmtRxWq, &pDev->state, WMT_STAT_RX); + waitRet = wmt_dev_rx_timeout(&pDev->rWmtRxWq); + + WMT_LOUD_FUNC("wmt_dev_rx_timeout returned\n"); + + if (0 == waitRet) { + WMT_ERR_FUNC("wmt_dev_rx_timeout: timeout \n"); + return -1; + } + else if (waitRet < 0) { + WMT_WARN_FUNC("wmt_dev_rx_timeout: interrupted by signal (%ld)\n", waitRet); + return waitRet; + } + WMT_DBG_FUNC("wmt_dev_rx_timeout, iRet(%ld)\n", waitRet); + /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + + if (0 == readLen) { + WMT_WARN_FUNC("wmt_ctrl_rx be signaled, but no rx data(%ld)\n", waitRet); + } + WMT_DBG_FUNC("readLen(%d) \n", readLen); + } + + if (readSize) { + *readSize = readLen ; + } + + return 0; + +} + + +INT32 +wmt_ctrl_tx_ex ( + const UINT8 *pData, + const UINT32 size, + UINT32 *writtenSize, + const MTK_WCN_BOOL bRawFlag + ) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + + if (NULL != writtenSize) { + *writtenSize = 0; + } + + /* sanity check */ + if (0 == size) { + WMT_WARN_FUNC("size to tx is 0\n"); + osal_assert(size); + return -1; + } + + /* if STP is not enabled yet, can't use this function. Use tx_raw instead */ + if ( !osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state) || + !osal_test_bit(WMT_STAT_STP_EN, &pDev->state) ) { + WMT_ERR_FUNC("wmt state(0x%lx) \n", pDev->state); + osal_assert(osal_test_bit(WMT_STAT_STP_EN, &pDev->state)); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + return -2; + } + + /* sanity ok, proceeding tx operation */ + /*retval = mtk_wcn_stp_send_data(data, size, WMTDRV_TYPE_WMT);*/ + mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); + if (bRawFlag) { + iRet = mtk_wcn_stp_send_data_raw(pData, size, WMT_TASK_INDX); + } + else { + iRet = mtk_wcn_stp_send_data(pData, size, WMT_TASK_INDX); + } + + if (iRet != size){ + WMT_WARN_FUNC("write(%d) written(%d)\n", size, iRet); + osal_assert(iRet == size); + } + + if (writtenSize) { + *writtenSize = iRet; + } + + return 0; + +} + +INT32 +wmt_ctrl_rx_flush ( + P_WMT_CTRL_DATA pWmtCtrlData + ) +{ + UINT32 type = pWmtCtrlData->au4CtrlData[0]; + + WMT_INFO_FUNC("flush rx %d queue\n", type); + mtk_wcn_stp_flush_rx_queue(type); + + return 0; +} + + +INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iret; + +/*psm should be disabled before wmt_ic_deinit*/ + P_DEV_WMT pDev = &gDevWmt; + if (osal_test_and_clear_bit(WMT_STAT_PWR, &pDev->state)) { + WMT_DBG_FUNC("on->off \n"); + iret = wmt_plat_pwr_ctrl(FUNC_OFF); + } + else { + WMT_WARN_FUNC("already off \n"); + iret = 0; + } + + return iret; +} + +INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iret; + + /*psm should be enabled right after wmt_ic_init*/ + P_DEV_WMT pDev = &gDevWmt; + if (osal_test_and_set_bit(WMT_STAT_PWR, &pDev->state)) { + WMT_WARN_FUNC("already on\n"); + iret = 0; + } + else { + WMT_DBG_FUNC("off->on \n"); + iret = wmt_plat_pwr_ctrl(FUNC_ON); + } + + return iret; +} + +INT32 wmt_ctrl_ul_cmd ( + P_DEV_WMT pWmtDev, + const UCHAR *pCmdStr + ) +{ + INT32 waitRet = -1; + P_OSAL_SIGNAL pCmdSignal; + P_OSAL_EVENT pCmdReq; + if (osal_test_and_set_bit(WMT_STAT_CMD, &pWmtDev->state)) { + WMT_WARN_FUNC("cmd buf is occupied by (%s) \n", pWmtDev->cCmd); + return -1; + } + + /* indicate baud rate change to user space app */ +#if 0 + INIT_COMPLETION(pWmtDev->cmd_comp); + pWmtDev->cmd_result = -1; + strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); + pWmtDev->cCmd[NAME_MAX] = '\0'; + wake_up_interruptible(&pWmtDev->cmd_wq); +#endif + + pCmdSignal = &pWmtDev->cmdResp; + osal_signal_init(pCmdSignal); + pCmdSignal->timeoutValue = 2000; + osal_strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); + pWmtDev->cCmd[NAME_MAX] = '\0'; + + pCmdReq = &pWmtDev->cmdReq; + + osal_trigger_event(&pWmtDev->cmdReq); + WMT_DBG_FUNC("str(%s) request ok\n", pCmdStr); + +// waitRet = wait_for_completion_interruptible_timeout(&pWmtDev->cmd_comp, msecs_to_jiffies(2000)); + waitRet = osal_wait_for_signal_timeout(pCmdSignal); + WMT_LOUD_FUNC("wait signal iRet:%d\n", waitRet); + if (0 == waitRet) { + WMT_ERR_FUNC("wait signal timeout \n"); + return -2; + } + + WMT_INFO_FUNC("str(%s) result(%d)\n", pCmdStr, pWmtDev->cmdResult); + + return pWmtDev->cmdResult; +} + +INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_RST); + return 0; +} + +INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_STAT); + return 0; +} + +INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet = 0; + UCHAR cmdStr[NAME_MAX + 1] = {0}; + /* un-register to STP-core for rx */ + iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, NULL); /* mtk_wcn_stp_register_event_cb */ + if (iRet) { + WMT_WARN_FUNC("stp_reg cb unregister fail(%d)\n", iRet); + return -1; + } + + if (WMT_HIF_UART == pDev->rWmtHifConf.hifType) { + + osal_snprintf(cmdStr, NAME_MAX, "close_stp"); + + iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (iRet) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); + return -2; + } + } + + osal_clear_bit(WMT_STAT_STP_OPEN, &pDev->state); + + return 0; +} + +INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UCHAR cmdStr[NAME_MAX + 1] = {0}; + + if (WMT_HIF_UART == pDev->rWmtHifConf.hifType) { + osal_snprintf(cmdStr, NAME_MAX, "open_stp"); + iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (iRet) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); + return -1; + } + } + + /* register to STP-core for rx */ + iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, wmt_dev_rx_event_cb); /* mtk_wcn_stp_register_event_cb */ + if (iRet) { + WMT_WARN_FUNC("stp_reg cb fail(%d)\n", iRet); + return -2; + } + + osal_set_bit(WMT_STAT_STP_OPEN, &pDev->state); + + return 0; +} + + +INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UCHAR cmdStr[NAME_MAX + 1] = {0}; + osal_snprintf(cmdStr, NAME_MAX, "srh_patch"); + iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (iRet) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); + return -1; + } + return 0; +} + + +INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + pWmtCtrlData->au4CtrlData[0] = pDev->patchNum; + return 0; +} + + +INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 downLoadSeq = 0; + P_WMT_PATCH_INFO pPatchinfo = NULL; + PUCHAR pNbuf = NULL; + PUCHAR pAbuf =NULL; + + downLoadSeq = pWmtCtrlData->au4CtrlData[0]; + WMT_DBG_FUNC("download seq is %d\n",downLoadSeq); + + pPatchinfo = pDev->pWmtPatchInfo + downLoadSeq - 1; + pNbuf = (PUCHAR)pWmtCtrlData->au4CtrlData[1]; + pAbuf = (PUCHAR)pWmtCtrlData->au4CtrlData[2]; + if(pPatchinfo) + { + osal_memcpy(pNbuf,pPatchinfo->patchName,osal_sizeof(pPatchinfo->patchName)); + osal_memcpy(pAbuf,pPatchinfo->addRess,osal_sizeof(pPatchinfo->addRess)); + WMT_DBG_FUNC("get 4 address bytes is 0x%2x,0x%2x,0x%2x,0x%2x",pAbuf[0],pAbuf[1],pAbuf[2],pAbuf[3]); + } + else + { + WMT_ERR_FUNC("NULL patchinfo pointer\n"); + } + + return 0; +} + + +INT32 wmt_ctrl_stp_conf_ex (WMT_STP_CONF_TYPE type, UINT32 value) +{ + INT32 iRet = -1; + switch (type) { + case WMT_STP_CONF_EN: + iRet = mtk_wcn_stp_enable(value); + break; + + case WMT_STP_CONF_RDY: + iRet = mtk_wcn_stp_ready(value); + break; + + case WMT_STP_CONF_MODE: + mtk_wcn_stp_set_mode(value); + iRet = 0; + break; + + default: + WMT_WARN_FUNC("invalid type(%d) value(%d) \n", type, value); + break; + } + return iRet; +} + + +INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 type; + UINT32 value; + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { + WMT_WARN_FUNC("CTRL_STP_ENABLE but invalid Handle of WmtStp \n"); + return -1; + } + + type = pWmtCtrlData->au4CtrlData[0]; + value = pWmtCtrlData->au4CtrlData[1]; + iRet = wmt_ctrl_stp_conf_ex(type, value); + + if (!iRet) { + if (WMT_STP_CONF_EN == type) { + if (value) { + osal_set_bit(WMT_STAT_STP_EN, &pDev->state); + WMT_DBG_FUNC("enable STP\n"); + } + else { + osal_clear_bit(WMT_STAT_STP_EN, &pDev->state); + WMT_DBG_FUNC("disable STP\n"); + } + } + } + + return iRet; +} + + +INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 patchSeq = pWmtCtrlData->au4CtrlData[0]; + WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (NULL != gDevWmt.pPatch) + { + wmt_dev_patch_put((osal_firmware **)&(gDevWmt.pPatch)); + } + WMT_DBG_FUNC("AF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (patchSeq == gDevWmt.patchNum) + { + WMT_DBG_FUNC("the %d patch has been download\n",patchSeq); + wmt_dev_patch_info_free(); + } + return 0; +} + + + +INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData) +{ + PUCHAR pBuf = (PUCHAR)pWmtCtrlData->au4CtrlData[0]; + osal_memcpy(pBuf, gDevWmt.cPatchName, osal_sizeof(gDevWmt.cPatchName)); + return 0; +} + + + + + +INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (NULL != gDevWmt.pNvram) + { + wmt_dev_patch_put((osal_firmware **)&(gDevWmt.pNvram)); + } + WMT_DBG_FUNC("AF free patch, gDevWmt.pNvram(0x%08x)\n", gDevWmt.pNvram); + return 0; +} + + +INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0x0; + UCHAR *pFileName = (UCHAR *)pWmtCtrlData->au4CtrlData[0]; + PUINT8 *ppBuf = (PUINT8 *)pWmtCtrlData->au4CtrlData[1]; + PUINT32 pSize = (PUINT32)pWmtCtrlData->au4CtrlData[2]; + + osal_firmware *pNvram = NULL; + + if ((NULL == pFileName) || (NULL == pSize)) + { + WMT_ERR_FUNC("parameter error, pFileName(0x%08x), pSize(0x%08x)\n", pFileName, pSize); + iRet = -1; + return iRet; + } + if (0 == wmt_dev_patch_get(pFileName, &pNvram, 0)) + { + *ppBuf = (PUINT8)(pNvram)->data; + *pSize = (pNvram)->size; + gDevWmt.pNvram = pNvram; + return 0; + } + return -1; + + +} + + +INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UCHAR *pFullPatchName = NULL; + UCHAR *pDefPatchName = NULL; + PUINT8 *ppBuf = (PUINT8 *)pWmtCtrlData->au4CtrlData[2]; + PUINT32 pSize = (PUINT32)pWmtCtrlData->au4CtrlData[3]; + + osal_firmware *pPatch = NULL; + pFullPatchName = (UCHAR *)pWmtCtrlData->au4CtrlData[1]; + WMT_DBG_FUNC("BF get patch, pPatch(0x%08x)\n", pPatch); + if ( (NULL != pFullPatchName) + && (0 == wmt_dev_patch_get(pFullPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM)) ) { + /*get full name patch success*/ + WMT_DBG_FUNC("get full patch name(%s) buf(0x%p) size(%d)\n", + pFullPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); + *ppBuf = (PUINT8)(pPatch)->data; + *pSize = (pPatch)->size; + gDevWmt.pPatch = pPatch; + return 0; + } + + pDefPatchName = (UCHAR *)pWmtCtrlData->au4CtrlData[0]; + if ( (NULL != pDefPatchName) + && (0 == wmt_dev_patch_get(pDefPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM)) ) { + WMT_DBG_FUNC("get def patch name(%s) buf(0x%p) size(%d)\n", + pDefPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); + /*get full name patch success*/ + *ppBuf = (PUINT8)(pPatch)->data; + *pSize = (pPatch)->size; + gDevWmt.pPatch = pPatch; + return 0; + } + return -1; + +} + +INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + CHAR cmdStr[NAME_MAX + 1] = {0}; + UINT32 u4Baudrate = pWmtCtrlData->au4CtrlData[0]; + UINT32 u4FlowCtrl = pWmtCtrlData->au4CtrlData[1]; + + WMT_DBG_FUNC("baud(%d), flowctrl(%d) \n", u4Baudrate, u4FlowCtrl); + + if (osal_test_bit(WMT_STAT_STP_OPEN, &gDevWmt.state)) { + osal_snprintf(cmdStr, NAME_MAX, "baud_%d_%d", u4Baudrate, u4FlowCtrl); + iRet = wmt_ctrl_ul_cmd(&gDevWmt, cmdStr); + if (iRet) { + WMT_WARN_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) fail(%d) \n", + u4Baudrate, + pWmtCtrlData->au4CtrlData[1], + iRet); + } + else { + WMT_DBG_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) ok\n", + u4Baudrate, + u4FlowCtrl); + } + } + else { + WMT_INFO_FUNC("CTRL_BAUDRATE but invalid Handle of WmtStp \n"); + } + return iRet; +} + +INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + UINT32 statBit = WMT_STAT_SDIO1_ON; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + WMT_SDIO_SLOT_NUM sdioSlotNum = pWmtCtrlData->au4CtrlData[0]; + ENUM_FUNC_STATE funcState = pWmtCtrlData->au4CtrlData[1]; + + if ((WMT_SDIO_SLOT_INVALID == sdioSlotNum) + || (WMT_SDIO_SLOT_MAX <= sdioSlotNum)) { + WMT_WARN_FUNC("CTRL_SDIO_SLOT(%d) but invalid slot num \n", sdioSlotNum); + return -1; + } + + WMT_DBG_FUNC("WMT_CTRL_SDIO_HW (0x%x, %d)\n", sdioSlotNum, funcState); + + if (WMT_SDIO_SLOT_SDIO2 == sdioSlotNum) { + statBit = WMT_STAT_SDIO2_ON; + } + + if (funcState) { + if (osal_test_and_set_bit(statBit, &pDev->state)) { + WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already ON \n", sdioSlotNum); + //still return 0 + iRet = 0; + } + else { + iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_ON); + } + } + else { + if (osal_test_and_clear_bit(statBit, &pDev->state)) { + iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_OFF); + } + else { + WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already OFF \n", sdioSlotNum); + //still return 0 + iRet = 0; + } + } + + return iRet; +} + +INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + UINT32 statBit = WMT_STAT_SDIO_WIFI_ON; + INT32 retry = 10; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + WMT_SDIO_FUNC_TYPE sdioFuncType = pWmtCtrlData->au4CtrlData[0]; + UINT32 u4On = pWmtCtrlData->au4CtrlData[1]; + + if (WMT_SDIO_FUNC_MAX <= sdioFuncType) { + WMT_ERR_FUNC("CTRL_SDIO_FUNC, invalid func type (%d) \n", sdioFuncType); + return -1; + } + + if (WMT_SDIO_FUNC_STP == sdioFuncType) { + statBit = WMT_STAT_SDIO_STP_ON; + } + + if (u4On) { + if (osal_test_bit(statBit, &pDev->state)) { + WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already ON \n", sdioFuncType); + iRet = 0; + } + else { + while (retry-- > 0 && iRet != 0) { + if (iRet) { + /* sleep 150ms before sdio slot ON ready */ + osal_msleep(150); + } + iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_TRUE); + if (HIF_SDIO_ERR_NOT_PROBED == iRet) { + /* not probed case, retry */ + continue; + } + else if (HIF_SDIO_ERR_CLT_NOT_REG == iRet){ + /* For WiFi, client not reg yet, no need to retry, WiFi function can work any time when wlan.ko is insert into system*/ + iRet = 0; + } + else + { + /* other fail cases, stop */ + break; + } + } + if (!retry || iRet) { + WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, TRUE) fail(%d) retry(%d)\n", sdioFuncType, iRet, retry); + } + else + { + osal_set_bit(statBit, &pDev->state); + } + } + } + else { + if (osal_test_bit(statBit, &pDev->state)) { + iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, FALSE) fail(%d)\n", sdioFuncType, iRet); + } + /*any way, set to OFF state*/ + osal_clear_bit(statBit, &pDev->state); + } + else { + WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already OFF \n", sdioFuncType); + iRet = 0; + } + } + + return iRet; +} + +#if 0 // TODO: [FixMe][GeorgeKuo]: remove unused function. get hwver from core is not needed. +INT32 wmt_ctrl_hwver_get(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + return 0; +} +#endif + +INT32 wmt_ctrl_hwidver_set(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + /* input sanity check is done in wmt_ctrl() */ + pDev->chip_id = (pWmtCtrlData->au4CtrlData[0] & 0xFFFF0000) >> 16; + pDev->hw_ver = pWmtCtrlData->au4CtrlData[0] & 0x0000FFFF; + pDev->fw_ver = pWmtCtrlData->au4CtrlData[1] & 0x0000FFFF; + + // TODO: [FixMe][GeorgeKuo] remove translated ENUM_WMTHWVER_TYPE_T in the future!!! + // Only use hw_ver read from hw. + pDev->eWmtHwVer = + (ENUM_WMTHWVER_TYPE_T)(pWmtCtrlData->au4CtrlData[1] & 0xFFFF0000) >> 16; + + return 0; +} + +static INT32 +wmt_ctrl_gps_sync_set ( + P_WMT_CTRL_DATA pData + ) +{ + INT32 iret; + + WMT_INFO_FUNC("ctrl GPS_SYNC(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); + iret = wmt_plat_gpio_ctrl(PIN_GPS_SYNC, + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); + + if (iret) { + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX, + iret); + } + + return 0; +} + + +static INT32 +wmt_ctrl_gps_lna_set ( + P_WMT_CTRL_DATA pData + ) +{ + INT32 iret; + + WMT_INFO_FUNC("ctrl GPS_LNA(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + iret = wmt_plat_gpio_ctrl(PIN_GPS_LNA, + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + + if (iret) { + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H, + iret); + } + + return 0; +} + + +INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + return 0; +} + +INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + pWmtCtrlData->au4CtrlData[0] = (UINT32)&pDev->rWmtGenConf; + + return 0; +} + +INT32 wmt_ctrl_others(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_ERR_FUNC("wmt_ctrl_others, invalid CTRL ID (%d)\n", pWmtCtrlData->ctrlId); + return -1; +} + + + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_dbg.c b/drivers/mtk_wcn_combo/common/core/wmt_dbg.c new file mode 100755 index 000000000000..03fb7a32a913 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_dbg.c @@ -0,0 +1,706 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief brief description + + Detailed descriptions here. + +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#include "wmt_dbg.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "psm_core.h" +#include "stp_core.h" + +#if CFG_WMT_DBG_SUPPORT + + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DEV]" + + + +#define WMT_DBG_PROCNAME "driver/wmt_dbg" + +static struct proc_dir_entry *gWmtDbgEntry = NULL; +COEX_BUF gCoexBuf; + +static INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd); +static INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3); + + + + + +const static WMT_DEV_DBG_FUNC wmt_dev_dbg_func[] = +{ + [0] = wmt_dbg_psm_ctrl, + [1] = wmt_dbg_psm_ctrl, + [2] = wmt_dbg_dsns_ctrl, + [3] = wmt_dbg_hwver_get, + [4] = wmt_dbg_assert_test, + [5] = wmt_dbg_inband_rst, + [6] = wmt_dbg_chip_rst, + [7] = wmt_dbg_func_ctrl, + [8] = wmt_dbg_raed_chipid, + [9] = wmt_dbg_wmt_dbg_level, + [0xa] = wmt_dbg_stp_dbg_level, + [0xb] = wmt_dbg_reg_read, + [0xc] = wmt_dbg_reg_write, + [0xd] = wmt_dbg_coex_test, + [0xe] = wmt_dbg_rst_ctrl, + [0xf] = wmt_dbg_ut_test, + [0x10] = wmt_dbg_efuse_read, + [0x11] = wmt_dbg_efuse_write, + [0x12] = wmt_dbg_sdio_ctrl, + [0x13] = wmt_dbg_stp_dbg_ctrl, + [0x14] = wmt_dbg_stp_dbg_log_ctrl, + [0x15] = wmt_dbg_wmt_assert_ctrl, +}; + +INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +#if CFG_WMT_PS_SUPPORT + if (0 == par2) + { + wmt_lib_ps_ctrl(0); + WMT_INFO_FUNC("disable PSM\n"); + } + else + { + par2 = (1 > par2 || 20000 < par2) ? STP_PSM_IDLE_TIME_SLEEP : par2; + wmt_lib_ps_set_idle_time(par2); + wmt_lib_ps_ctrl(1); + WMT_INFO_FUNC("enable PSM, idle to sleep time = %d ms\n", par2); + } +#else + WMT_INFO_FUNC("WMT PS not supported\n"); +#endif + return 0; +} + +INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (WMTDSNS_FM_DISABLE <= par2 && WMTDSNS_MAX > par2 ) + { + WMT_INFO_FUNC("DSNS type (%d)\n", par2); + mtk_wcn_wmt_dsns_ctrl(par2); + } + else + { + WMT_WARN_FUNC("invalid DSNS type\n"); + } + return 0; +} + +INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("query chip version\n"); + mtk_wcn_wmt_hwver_get(); + return 0; +} + +INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par3) + { + //par2 = 0: send assert command + //par2 != 0: send exception command + return wmt_dbg_cmd_test_api(0 == par2 ? 0 : 1); + } + else + { + INT32 sec = 8; + INT32 times = 0; + times = par3; + do{ + WMT_INFO_FUNC("Send Assert Command per 8 secs!!\n"); + wmt_dbg_cmd_test_api(0); + osal_msleep(sec * 1000); + }while(--times); + } + return 0; +} + +INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd) +{ + + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp ) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp ->signal; + + pOp ->op.opId = WMT_OPID_CMD_TEST; + + pSignal->timeoutValue= MAX_EACH_WMT_CMD; + /*this test command should be run with usb cable connected, so no host awake is needed*/ + //wmt_lib_host_awake_get(); + switch (cmd) + { + case WMTDRV_CMD_ASSERT: + pOp->op.au4OpData[0] = 0; + break; + case WMTDRV_CMD_EXCEPTION: + pOp->op.au4OpData[0] = 1; + break; + default: + if (WMTDRV_CMD_COEXDBG_00 <= cmd && WMTDRV_CMD_COEXDBG_15 >= cmd) + { + pOp->op.au4OpData[0] = 2; + pOp->op.au4OpData[1] = cmd - 2; + } + else + { + pOp->op.au4OpData[0] = 0xff; + pOp->op.au4OpData[1] = 0xff; + } + pOp->op.au4OpData[2] = (ULONG)gCoexBuf.buffer; + pOp->op.au4OpData[3] = osal_sizeof(gCoexBuf.buffer); + break; + } + WMT_INFO_FUNC("CMD_TEST, opid(%d), par(%d, %d)\n", pOp->op.opId, pOp->op.au4OpData[0], pOp->op.au4OpData[1]); + /*wake up chip first*/ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if ((cmd != WMTDRV_CMD_ASSERT) && (cmd != WMTDRV_CMD_EXCEPTION)) + { + if (MTK_WCN_BOOL_FALSE == bRet) + { + gCoexBuf.availSize = 0; + } + else + { + gCoexBuf.availSize = pOp->op.au4OpData[3]; + WMT_INFO_FUNC("gCoexBuf.availSize = %d\n", gCoexBuf.availSize); + } + } + //wmt_lib_host_awake_put(); + WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", \ + pOp->op.opId, \ + pOp->op.au4OpData[0], \ + pOp->op.au4OpData[1], \ + bRet, \ + MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"\ + ); + + return 0; +} + +INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par2) + { + WMT_INFO_FUNC("inband reset test!!\n"); + mtk_wcn_stp_inband_reset(); + } + else + { + WMT_INFO_FUNC("STP context reset in host side!!\n"); + mtk_wcn_stp_flush_context(); + } + + return 0; +} + +INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par2) + { + if (mtk_wcn_stp_is_ready()) + { + WMT_INFO_FUNC("whole chip reset test\n"); + wmt_lib_cmb_rst(WMTRSTSRC_RESET_TEST); + } + else + { + WMT_INFO_FUNC("STP not ready , not to launch whole chip reset test\n"); + } + } + else if (1 == par2) + { + WMT_INFO_FUNC("chip hardware reset test\n"); + wmt_lib_hw_rst(); + } + else + { + WMT_INFO_FUNC("chip software reset test\n"); + wmt_lib_sw_rst(1); + } + return 0; +} + +INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (WMTDRV_TYPE_WMT > par2 || WMTDRV_TYPE_LPBK == par2) + { + if (0 == par3) + { + WMT_INFO_FUNC("function off test, type(%d)\n", par2); + mtk_wcn_wmt_func_off(par2); + } + else + { + WMT_INFO_FUNC("function on test, type(%d)\n", par2); + mtk_wcn_wmt_func_on(par2); + } + } + else + { + WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2); + } + return 0; +} + +INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("chip version = %d\n", wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER)); + return 0; +} + +INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (WMT_LOG_ERR <= par2 && WMT_LOG_LOUD >= par2) ? par2 : WMT_LOG_INFO; + wmt_lib_dbg_level_set(par2); + WMT_INFO_FUNC("set wmt log level to %d\n", par2); + return 0; +} + +INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (0 <= par2 && 4 >= par2) ? par2 : 2; + mtk_wcn_stp_dbg_level(par2); + WMT_INFO_FUNC("set stp log level to %d\n", par2); + return 0; + +} + +INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3) +{ + //par2-->register address + //par3-->register mask + UINT32 value = 0x0; + UINT32 iRet = -1; +#if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(0, par2, &value, par3); + ENABLE_PSM_MONITOR(); +#endif + iRet = wmt_lib_reg_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", \ + par2, \ + par3, \ + iRet != 0 ? "failed" : "succeed", \ + iRet != 0 ? -1: value\ + ); + return 0; +} + +INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3) +{ + //par2-->register address + //par3-->value to set + UINT32 iRet = -1; + #if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(1, par2, &par3, 0xffffffff); + ENABLE_PSM_MONITOR(); + #endif + iRet = wmt_lib_reg_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip register (0x%08x) with value (0x%08x) %s\n", \ + par2, \ + par3, \ + iRet != 0 ? "failed" : "succeed"\ + ); + return 0; +} + +INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3) +{ + //par2-->efuse address + //par3-->register mask + UINT32 value = 0x0; + UINT32 iRet = -1; + + iRet = wmt_lib_efuse_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", \ + par2, \ + par3, \ + iRet != 0 ? "failed" : "succeed", \ + iRet != 0 ? -1: value\ + ); + return 0; +} + +INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3) +{ + //par2-->efuse address + //par3-->value to set + UINT32 iRet = -1; + iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", \ + par2, \ + par3, \ + iRet != 0 ? "failed" : "succeed"\ + ); + return 0; +} + + +INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 iRet = -1; + iRet = wmt_lib_sdio_ctrl (0 != par2 ? 1 : 0); + WMT_INFO_FUNC("ctrl SDIO function %s\n", 0 == iRet ? "succeed" : "failed"); + return 0; +} + + +INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (1 < par2) + { + mtk_wcn_stp_dbg_dump_package(); + return 0; + } + WMT_INFO_FUNC("%s stp debug function\n", 0 == par2 ? "disable" : "enable"); + if (0 == par2) + { + mtk_wcn_stp_dbg_disable(); + } + else if (1 == par2) + { + mtk_wcn_stp_dbg_enable(); + } + return 0; +} + +INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + mtk_wcn_stp_dbg_log_ctrl(0 != par2 ? 1 : 0); + return 0; +} + + + +INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + mtk_wcn_stp_coredump_flag_ctrl(0 != par2 ? 1 : 0); + return 0; +} + + +INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("coexistance test cmd!!\n"); + return wmt_dbg_cmd_test_api(par2 + WMTDRV_CMD_COEXDBG_00); +} + +INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s audo rst\n", 0 == par2 ? "disable" : "enable"); + mtk_wcn_stp_set_auto_rst(0 == par2 ? 0 : 1); + return 0; +} + +static INT32 wmt_dev_dbg_read(CHAR *page, CHAR **start, off_t off, INT32 count, INT32 *eof, void *data){ + INT32 len = 0; + + if(off > 0){ + len = 0; + } else { + /*len = sprintf(page, "%d\n", g_psm_enable);*/ + if ( gCoexBuf.availSize <= 0) + { + WMT_INFO_FUNC("no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"); + len = osal_sprintf(page, "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"); + } + else + { + INT32 i = 0; + /*we do not check page buffer, because there are only 100 bytes in g_coex_buf, no reason page buffer is not enough, a bomb is placed here on unexpected condition*/ + for (i = 0; i < gCoexBuf.availSize; i++) + { + len += osal_sprintf(page + len, "0x%02x ", gCoexBuf.buffer[i]); + } + len += osal_sprintf(page + len, "\n"); + } + } + gCoexBuf.availSize = 0; + return len; +} + +INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3) +{ + + INT32 i = 0; + INT32 j = 0; + INT32 iRet = 0; + + i = 20; + while((i--) > 0){ + WMT_INFO_FUNC("#### UT WMT and STP Function On/Off .... %d\n", i); + j = 10; + while((j--) > 0){ + WMT_INFO_FUNC("#### BT On .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### GPS On .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### FM On .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### WIFI On .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### BT Off .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### GPS Off ....(%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### FM Off .... (%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + WMT_INFO_FUNC("#### WIFI Off ....(%d, %d) \n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI); + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + } + if(iRet == MTK_WCN_BOOL_FALSE){ + break; + } + } + if(iRet == MTK_WCN_BOOL_FALSE){ + WMT_INFO_FUNC("#### UT FAIL!!\n"); + } else { + WMT_INFO_FUNC("#### UT PASS!!\n"); + } + return iRet; +} + + +static INT32 wmt_dev_dbg_write(struct file *file, const CHAR *buffer, ULONG count, void *data){ + + CHAR buf[256]; + CHAR *pBuf; + ULONG len = count; + INT32 x = 0,y = 0, z=0; + CHAR *pToken = NULL; + CHAR *pDelimiter = " \t"; + + WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32)len); + if(len >= osal_sizeof(buf)){ + WMT_ERR_FUNC("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if(copy_from_user(buf, buffer, len)){ + return -EFAULT; + } + buf[len] = '\0'; + WMT_INFO_FUNC("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + x = NULL != pToken ? osal_strtol(pToken, NULL, 16) : 0; + + pToken = osal_strsep(&pBuf, "\t\n "); + if(pToken != NULL){ + y = osal_strtol(pToken, NULL, 16); + WMT_INFO_FUNC("y = 0x%08x \n\r", y); + } else { + y = 3000; + /*efuse, register read write default value*/ + if(0x11 == x || 0x12 == x || 0x13 == x) { + y = 0x80000000; + } + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if(pToken != NULL){ + z = osal_strtol(pToken, NULL, 16); + } else { + z = 10; + /*efuse, register read write default value*/ + if(0x11 == x || 0x12 == x || 0x13 == x) { + z = 0xffffffff; + } + } + + WMT_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + if (osal_array_size(wmt_dev_dbg_func) > x && NULL != wmt_dev_dbg_func[x]) + { + (*wmt_dev_dbg_func[x])(x, y, z); + } + else + { + WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x); + } + return len; +} + +INT32 wmt_dev_dbg_setup(VOID) +{ + gWmtDbgEntry = create_proc_entry(WMT_DBG_PROCNAME, 0664, NULL); + if(gWmtDbgEntry == NULL){ + WMT_ERR_FUNC("Unable to create /proc entry\n\r"); + return -1; + } + gWmtDbgEntry->read_proc = wmt_dev_dbg_read; + gWmtDbgEntry->write_proc = wmt_dev_dbg_write; + return 0; +} + +INT32 wmt_dev_dbg_remove(VOID) +{ + if (NULL != gWmtDbgEntry) + { + remove_proc_entry(WMT_DBG_PROCNAME, NULL); + } +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_deinit(); +#endif + return 0; +} +#endif + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_exp.c b/drivers/mtk_wcn_combo/common/core/wmt_exp.c new file mode 100755 index 000000000000..915d882d95f9 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_exp.c @@ -0,0 +1,414 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-EXP]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include +#include +#include + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static MTK_WCN_BOOL +mtk_wcn_wmt_func_ctrl ( + ENUM_WMTDRV_TYPE_T type, + ENUM_WMT_OPID_T opId + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static MTK_WCN_BOOL +mtk_wcn_wmt_func_ctrl ( + ENUM_WMTDRV_TYPE_T type, + ENUM_WMT_OPID_T opId + ) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = opId; + pOp->op.au4OpData[0] = type; + pSignal->timeoutValue= (WMT_OPID_FUNC_ON == pOp->op.opId) ? MAX_FUNC_ON_TIME : MAX_FUNC_OFF_TIME; + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + + /*do not check return value, we will do this either way*/ + wmt_lib_host_awake_get(); + /*wake up chip first*/ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + wmt_lib_host_awake_put(); + + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + } + else { + WMT_INFO_FUNC("OPID(%d) type(%d) ok\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + } + return bRet; +} + +MTK_WCN_BOOL +mtk_wcn_wmt_func_off ( + ENUM_WMTDRV_TYPE_T type + ) +{ + MTK_WCN_BOOL ret; + + if(type == WMTDRV_TYPE_BT) + { + osal_printtimeofday("############ BT OFF ====>"); + } + + ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_OFF); + + if(type == WMTDRV_TYPE_BT) + { + osal_printtimeofday("############ BT OFF <===="); + } + + return ret; +} + +MTK_WCN_BOOL +mtk_wcn_wmt_func_on ( + ENUM_WMTDRV_TYPE_T type + ) +{ + MTK_WCN_BOOL ret; + + if(type == WMTDRV_TYPE_BT) + { + osal_printtimeofday("############ BT ON ====>"); + } + + ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_ON); + + if(type == WMTDRV_TYPE_BT) + { + osal_printtimeofday(" ############BT ON <===="); + } + + return ret; +} + +/* +return value: +enable/disable thermal sensor function: true(1)/false(0) +read thermal sensor function:thermal value + +*/ +INT8 +mtk_wcn_wmt_therm_ctrl ( + ENUM_WMTTHERM_TYPE_T eType + ) +{ + P_OSAL_OP pOp; + P_WMT_OP pOpData; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /*parameter validation check*/ + if( WMTTHERM_MAX < eType || WMTTHERM_ENABLE > eType){ + WMT_ERR_FUNC("invalid thermal control command (%d)\n", eType); + return MTK_WCN_BOOL_FALSE; + } + + /*check if chip support thermal control function or not*/ + bRet = wmt_lib_is_therm_ctrl_support(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_ERR_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pOpData = &pOp->op; + pOpData->opId = WMT_OPID_THERM_CTRL; + /*parameter fill*/ + pOpData->au4OpData[0] = eType; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", + pOpData->opId, + pOpData->au4OpData[0]); + /*0xFF means read error occurs*/ + pOpData->au4OpData[1] = (eType == WMTTHERM_READ) ? 0xFF : MTK_WCN_BOOL_FALSE;/*will return to function driver*/ + } + else { + WMT_INFO_FUNC("OPID(%d) type(%d) return(%d) ok\n\n", + pOpData->opId, + pOpData->au4OpData[0], + pOpData->au4OpData[1]); + } + /*return value will be put to lxop->op.au4OpData[1]*/ + WMT_DBG_FUNC("therm ctrl type(%d), iRet(0x%08x) \n", eType, pOpData->au4OpData[1]); + return (INT8)pOpData->au4OpData[1]; +} + +ENUM_WMTHWVER_TYPE_T +mtk_wcn_wmt_hwver_get (VOID) +{ + // TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type + // TODO: how do we extend for new chip and newer revision? + // TODO: This way is hard to extend + return wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER); +} + +MTK_WCN_BOOL +mtk_wcn_wmt_dsns_ctrl ( + ENUM_WMTDSNS_TYPE_T eType + ) +{ + P_OSAL_OP pOp; + P_WMT_OP pOpData; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + if (WMTDSNS_MAX <= eType) { + WMT_ERR_FUNC("invalid desense control command (%d)\n", eType); + return MTK_WCN_BOOL_FALSE; + } + + /*check if chip support thermal control function or not*/ + bRet = wmt_lib_is_dsns_ctrl_support(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_ERR_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pOpData = &pOp->op; + pOpData->opId = WMT_OPID_DSNS; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + /*parameter fill*/ + if ((WMTDSNS_FM_DISABLE <= eType) && (WMTDSNS_FM_GPS_ENABLE >= eType)) { + pOpData->au4OpData[0] = WMTDRV_TYPE_FM; + pOpData->au4OpData[1] = eType; + } + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", + pOpData->opId, + pOpData->au4OpData[0]); + } + else { + WMT_INFO_FUNC("OPID(%d) type(%d) ok\n\n", + pOpData->opId, + pOpData->au4OpData[0]); + } + + return bRet; +} + +INT32 +mtk_wcn_wmt_msgcb_reg ( + ENUM_WMTDRV_TYPE_T eType, + PF_WMT_CB pCb + ) +{ + return (INT32)wmt_lib_msgcb_reg(eType, pCb); +} + +INT32 +mtk_wcn_wmt_msgcb_unreg ( + ENUM_WMTDRV_TYPE_T eType + ) +{ + return (INT32)wmt_lib_msgcb_unreg(eType); +} + +INT32 +mtk_wcn_stp_wmt_sdio_op_reg ( + PF_WMT_SDIO_PSOP own_cb + ) +{ + wmt_lib_ps_set_sdio_psop(own_cb); + return 0; +} + + +INT32 +mtk_wcn_stp_wmt_sdio_host_awake( + VOID + ) +{ + wmt_lib_ps_irq_cb(); + return 0; +} + +MTK_WCN_BOOL mtk_wcn_wmt_assert ( + void + ) +{ + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp ) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp ->signal; + + pOp ->op.opId = WMT_OPID_CMD_TEST; + + pSignal->timeoutValue= MAX_EACH_WMT_CMD; + /*this test command should be run with usb cable connected, so no host awake is needed*/ + //wmt_lib_host_awake_get(); + pOp->op.au4OpData[0] = 0; + + /*wake up chip first*/ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + //wmt_lib_host_awake_put(); + WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", \ + pOp->op.opId, \ + pOp->op.au4OpData[0], \ + pOp->op.au4OpData[1], \ + bRet, \ + MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"\ + ); + + return bRet; +} + +extern INT32 mtk_wcn_wmt_chipid_query (VOID) +{ + return mtk_wcn_hif_sdio_query_chipid(0); +} + + + +EXPORT_SYMBOL(mtk_wcn_wmt_assert); +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); +EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); +EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); +EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); +EXPORT_SYMBOL(mtk_wcn_wmt_func_on); +EXPORT_SYMBOL(mtk_wcn_wmt_func_off); +EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query); + + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_func.c b/drivers/mtk_wcn_combo/common/core/wmt_func.c new file mode 100755 index 000000000000..cf71766e34f7 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_func.c @@ -0,0 +1,510 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-FUNC]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_func.h" +#include "wmt_lib.h" +#include "wmt_core.h" + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_FUNC_BT_SUPPORT + +static INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + + WMT_FUNC_OPS wmt_func_bt_ops = { + //BT subsystem function on/off + .func_on = wmt_func_bt_on, + .func_off = wmt_func_bt_off + }; +#endif + +#if CFG_FUNC_FM_SUPPORT + +static INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + + WMT_FUNC_OPS wmt_func_fm_ops = { + //FM subsystem function on/off + .func_on = wmt_func_fm_on, + .func_off = wmt_func_fm_off + }; +#endif + +#if CFG_FUNC_GPS_SUPPORT + +static INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + + WMT_FUNC_OPS wmt_func_gps_ops = { + //GPS subsystem function on/off + .func_on = wmt_func_gps_on, + .func_off = wmt_func_gps_off + + }; + +#endif + +#if CFG_FUNC_WIFI_SUPPORT +static INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + + WMT_FUNC_OPS wmt_func_wifi_ops = { + //Wi-Fi subsystem function on/off + .func_on = wmt_func_wifi_on, + .func_off = wmt_func_wifi_off + }; +#endif + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_FUNC_GPS_SUPPORT +CMB_PIN_CTRL_REG eediPinOhRegs[] = { + { + //pull down ctrl register + .regAddr = 0x80050020, + .regValue = ~(0x1UL << 5), + .regMask = 0x00000020UL, + }, + { + //pull up ctrl register + .regAddr = 0x80050000, + .regValue = 0x1UL << 5, + .regMask = 0x00000020UL, + }, + { + //iomode ctrl register + .regAddr = 0x80050110, + .regValue = 0x1UL << 0, + .regMask = 0x00000007UL, + }, + { + //output high/low ctrl register + .regAddr = 0x80050040, + .regValue = 0x1UL << 5, + .regMask = 0x00000020UL, + } + +}; +CMB_PIN_CTRL_REG eediPinOlRegs[] = { + { + .regAddr = 0x80050020, + .regValue = 0x1UL << 5, + .regMask = 0x00000020UL, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1UL << 5), + .regMask = 0x00000020UL, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1UL << 0, + .regMask = 0x00000007UL, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1UL << 5), + .regMask = 0x00000020UL, + } +}; + +CMB_PIN_CTRL_REG eedoPinOhRegs[] = +{ + { + .regAddr = 0x80050020, + .regValue = ~(0x1UL << 7), + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050000, + .regValue = 0x1UL << 7, + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1UL << 12, + .regMask = 0x00007000UL, + }, + { + .regAddr = 0x80050040, + .regValue = 0x1UL << 7, + .regMask = 0x00000080UL, + } +}; + + +CMB_PIN_CTRL_REG eedoPinOlRegs[] = +{ + { + .regAddr = 0x80050020, + .regValue = 0x1UL << 7, + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1UL << 7), + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1UL << 12, + .regMask = 0x00007000UL, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1UL << 7), + .regMask = 0x00000080UL, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOnRegs[] = +{ + { + .regAddr = 0x80050110, + .regValue = 0x3UL << 20, + .regMask = 0x7UL << 20, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOffRegs[] = +{ + { + .regAddr = 0x80050110, + .regValue = 0x0UL << 20, + .regMask = 0x7UL << 20, + } +}; + +//templete usage for GPIO control +CMB_PIN_CTRL gCmbPinCtrl[3] = +{ + { + .pinId = CMB_PIN_EEDI_ID, + .regNum = 4, + .pFuncOnArray = eediPinOhRegs, + .pFuncOffArray = eediPinOlRegs, + }, + { + .pinId = CMB_PIN_EEDO_ID, + .regNum = 4, + .pFuncOnArray = eedoPinOhRegs, + .pFuncOffArray = eedoPinOlRegs, + }, + { + .pinId = CMB_PIN_GSYNC_ID, + .regNum = 1, + .pFuncOnArray = gsyncPinOnRegs, + .pFuncOffArray = gsyncPinOffRegs, + } +}; +#endif + + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if CFG_FUNC_BT_SUPPORT + +INT32 _osal_inline_ wmt_func_bt_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn BT subsystem wmt command*/ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + //return wmt_func_bt_ctrl(FUNC_ON); + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE); +} + +INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + //return wmt_func_bt_ctrl(FUNC_OFF); + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE); +} + +#endif + +#if CFG_FUNC_GPS_SUPPORT + +INT32 _osal_inline_ wmt_func_gps_ctrl (ENUM_FUNC_STATE funcState) +{ + /*send turn GPS subsystem wmt command*/ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_GPS, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_gps_pre_ctrl(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf, ENUM_FUNC_STATE funcStatus) +{ + UINT32 i = 0; + UINT32 iRet =0; + UINT32 regAddr = 0; + UINT32 regValue = 0; + UINT32 regMask = 0; + UINT32 regNum = 0; + P_CMB_PIN_CTRL_REG pReg; + P_CMB_PIN_CTRL pCmbPinCtrl; + WMT_CTRL_DATA ctrlData; + WMT_IC_PIN_ID wmtIcPinId = WMT_IC_PIN_MAX; + //sanity check + if (FUNC_ON != funcStatus && FUNC_OFF != funcStatus) + { + WMT_ERR_FUNC("invalid funcStatus(%d)\n", funcStatus); + return -1; + } + + //turn on GPS sync function on both side + ctrlData.ctrlId = WMT_CTRL_GPS_SYNC_SET; + ctrlData.au4CtrlData[0] = (FUNC_ON == funcStatus) ? 1 : 0; + iRet = wmt_ctrl(&ctrlData) ; + if (iRet) { + /*we suppose this would never print*/ + WMT_ERR_FUNC("ctrl GPS_SYNC_SET(%d) fail, ret(%d)\n", funcStatus, iRet); + // TODO:[FixMe][George] error handling? + return -2; + } + else { + WMT_INFO_FUNC("ctrl GPS_SYNC_SET(%d) ok \n", funcStatus); + } + if((NULL == pOps->ic_pin_ctrl) || + (0 > pOps->ic_pin_ctrl( + WMT_IC_PIN_GSYNC, + FUNC_ON == funcStatus ? WMT_IC_PIN_MUX : WMT_IC_PIN_GPIO, + 1)))/*WMT_IC_PIN_GSYNC*/ + { + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; + regNum = pCmbPinCtrl->regNum; + for (i = 0; i < regNum; i++) + { + pReg = FUNC_ON == funcStatus ? &pCmbPinCtrl->pFuncOnArray[i] : &pCmbPinCtrl->pFuncOffArray[i]; + regAddr = pReg->regAddr; + regValue = pReg->regValue; + regMask = pReg->regMask; + + iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC("set reg for GPS_SYNC function fail(%d) \n", iRet); + //TODO:[FixMe][Chaozhong] error handling? + return -2; + } + + } + } + else + { + WMT_INFO_FUNC("set reg for GPS_SYNC function okay by chip ic_pin_ctrl\n"); + } + WMT_INFO_FUNC("ctrl combo chip gps sync function succeed\n"); + //turn on GPS lna ctrl function + if (NULL != pConf) + { + if (0 == pConf->wmt_gps_lna_enable) + { + + WMT_INFO_FUNC("host pin used for gps lna\n"); + //host LNA ctrl pin needed + ctrlData.ctrlId = WMT_CTRL_GPS_LNA_SET; + ctrlData.au4CtrlData[0] = FUNC_ON == funcStatus ? 1 : 0 ; + iRet = wmt_ctrl(&ctrlData) ; + if (iRet) { + /*we suppose this would never print*/ + WMT_ERR_FUNC("ctrl host GPS_LNA output high fail, ret(%d)\n", iRet); + // TODO:[FixMe][Chaozhong] error handling? + return -3; + } + else { + WMT_INFO_FUNC("ctrl host gps lna function succeed\n"); + } + } + else + { + WMT_INFO_FUNC("combo chip pin(%s) used for gps lna\n", 0 == pConf->wmt_gps_lna_pin ? "EEDI" : "EEDO"); + wmtIcPinId = 0 == pConf->wmt_gps_lna_pin ? WMT_IC_PIN_EEDI: WMT_IC_PIN_EEDO; + if((NULL == pOps->ic_pin_ctrl) || + (0 > pOps->ic_pin_ctrl( + wmtIcPinId, + FUNC_ON == funcStatus ? WMT_IC_PIN_GPIO_HIGH : WMT_IC_PIN_GPIO_LOW, + 1)))/*WMT_IC_PIN_GSYNC*/ + { + if (0 == pConf->wmt_gps_lna_pin) + { + //EEDI needed + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDI_ID]; + } + else if (1 == pConf->wmt_gps_lna_pin) + { + //EEDO needed + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDO_ID]; + } + regNum = pCmbPinCtrl->regNum; + for (i = 0; i < regNum; i++) + { + pReg = FUNC_ON == funcStatus ? &pCmbPinCtrl->pFuncOnArray[i] : &pCmbPinCtrl->pFuncOffArray[i]; + regAddr = pReg->regAddr; + regValue = pReg->regValue; + regMask = pReg->regMask; + + iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC("set reg for GPS_LNA function fail(%d) \n", iRet); + //TODO:[FixMe][Chaozhong] error handling? + return -3; + } + } + WMT_INFO_FUNC("ctrl combo chip gps lna succeed\n"); + } + else + { + WMT_INFO_FUNC("set reg for GPS_LNA function okay by chip ic_pin_ctrl\n"); + } + } + } + return 0; + +} + +INT32 wmt_func_gps_pre_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_ON); +} + +INT32 wmt_func_gps_pre_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_OFF); +} + + +INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + iRet = wmt_func_gps_pre_on(pOps, pConf); + if (0 == iRet) + { + iRet = wmt_func_gps_ctrl(FUNC_ON); + } + return iRet; +} + +INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + iRet = wmt_func_gps_pre_off(pOps, pConf); + if (0 == iRet) + { + iRet = wmt_func_gps_ctrl(FUNC_OFF); + } + return iRet; + +} +#endif + +#if CFG_FUNC_FM_SUPPORT + +INT32 _osal_inline_ wmt_func_fm_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn FM subsystem wmt command*/ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + + +INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + //return wmt_func_fm_ctrl(FUNC_ON); + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_TRUE); +} + +INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + //return wmt_func_fm_ctrl(FUNC_OFF); + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_FALSE); +} + +#endif + +#if CFG_FUNC_WIFI_SUPPORT + +INT32 +wmt_func_wifi_ctrl ( + ENUM_FUNC_STATE funcState + ) +{ + INT32 iRet = 0; + UINT32 ctrlPa1 = WMT_SDIO_FUNC_WIFI; + UINT32 ctrlPa2 = (FUNC_ON == funcState) ? 1 : 0; /* turn on Wi-Fi driver */ + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ; + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: turn on WIFI function fail (%d)", iRet); + return -1; + } + return 0; +} + + +INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_func_wifi_ctrl(FUNC_ON); +} + +INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_func_wifi_ctrl(FUNC_OFF); +} +#endif + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c b/drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c new file mode 100755 index 000000000000..fe029aa5937e --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c @@ -0,0 +1,1906 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-IC]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define MT6620E2_PATCH_FRAG_SIZE (900) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +#define CFG_WMT_BT_PORT2 (0) /* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC,*/ + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if !(CFG_WMT_MULTI_PATCH) +static UCHAR gDefPatchName[NAME_MAX + 1]; +#endif +static UCHAR gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6620_info = NULL; + +static UCHAR WMT_WAKEUP_DIS_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x04}; +static UCHAR WMT_WAKEUP_DIS_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x04}; +#if 0 +static UCHAR WMT_WAKEUP_EN_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x05}; +static UCHAR WMT_WAKEUP_EN_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x05}; +#endif +static UCHAR WMT_QUERY_BAUD_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x02}; +static UCHAR WMT_QUERY_BAUD_EVT_115200[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00}; +static UCHAR WMT_QUERY_BAUD_EVT_X[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB}; +static UCHAR WMT_QUERY_STP_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x04}; +static UCHAR WMT_QUERY_STP_EVT_DEFAULT[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00}; +static UCHAR WMT_QUERY_STP_EVT_UART[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01}; +static UCHAR WMT_SET_BAUD_CMD_X[] = {0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB}; +static UCHAR WMT_SET_BAUD_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x01}; +static UCHAR WMT_SET_WAKEUP_WAKE_CMD_RAW[] = {0xFF}; +static UCHAR WMT_SET_WAKEUP_WAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03}; +#if CFG_WMT_MULTI_PATCH +static UCHAR WMT_PATCH_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x64,0x0E,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff}; +static UCHAR WMT_PATCH_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01}; +static UCHAR WMT_PATCH_P_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x38,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff}; +static UCHAR WMT_PATCH_P_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01}; +#endif + +static UCHAR WMT_PATCH_CMD[] = {0x01, 0x01, 0x00, 0x00, 0x00}; +static UCHAR WMT_PATCH_EVT[] = {0x02, 0x01, 0x01, 0x00, 0x00}; +static UCHAR WMT_RESET_CMD[] = {0x01, 0x07, 0x01, 0x00, 0x04}; +static UCHAR WMT_RESET_EVT[] = {0x02, 0x07, 0x01, 0x00, 0x00}; +#if CFG_WMT_BT_PORT2 +static UCHAR WMT_BTP2_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01}; +static UCHAR WMT_BTP2_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +#endif +/*coex cmd/evt++*/ +static UCHAR WMT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x04, 0x00, 0x01, 0xAA, 0xBB, 0xCC}; +static UCHAR WMT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_BT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB,0xCC,0xDD,0xEE,0xFF,0xAA}; +static UCHAR WMT_BT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00,0x00,0x00,0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA}; +static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_PTA_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE}; +static UCHAR WMT_PTA_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_MISC_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB}; +static UCHAR WMT_MISC_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +/*coex cmd/evt--*/ +static UCHAR WMT_SET_STP_CMD[] = {0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01}; +static UCHAR WMT_SET_STP_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x03}; +static UCHAR WMT_STRAP_CONF_CMD_FM_COMM[] = {0x01, 0x05, 0x02, 0x00, 0x02, 0x02}; +static UCHAR WMT_STRAP_CONF_EVT[] = {0x02, 0x05, 0x02, 0x00, 0x00, 0x02}; +#if 0 +static UCHAR WMT_SET_OSC32K_BYPASS_CMD[]= {0x01, 0x0A, 0x01, 0x00, 0x05}; +static UCHAR WMT_SET_OSC32K_BYPASS_EVT[]= {0x02, 0x0A, 0x01, 0x00, 0x00}; +#endif + +static UCHAR WMT_CORE_DUMP_LEVEL_04_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UCHAR WMT_CORE_DUMP_LEVEL_04_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00}; + +/* enable all interrupt */ +static UCHAR WMT_SET_ALLINT_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0x00, 0x03, 0x05, 0x80/*addr:0x80050300*/ + ,0x00, 0xC4, 0x00, 0x00/*value:0x0000C400*/ + ,0x00, 0xC4, 0x00, 0x00/*mask:0x0000C400*/ +}; + +static UCHAR WMT_SET_ALLINT_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UCHAR WMT_SET_SWLA_REG_CMD[] = {0x01, 0x08, 0x1C, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ + ,0x10, 0x01, 0x05, 0x80/*addr:0x80050110*/ + ,0x10, 0x10, 0x01, 0x00/*value:0x00011010*/ + ,0xF0, 0xF0, 0x0F, 0x00/*mask:0x000FF0F0*/ + ,0x40, 0x01, 0x05, 0x80/*addr:0x80050140*/ + ,0x00, 0x10, 0x01, 0x00/*value:0x00011000*/ + ,0x00, 0xF0, 0x0F, 0x00/*mask:0x000FF000*/ +}; +static UCHAR WMT_SET_SWLA_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UCHAR WMT_SET_MCUCLK_REG_CMD[] = {0x01, 0x08, (4 + 12*4), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + ,0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + ,0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + ,0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + ,0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + ,0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + ,0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UCHAR WMT_SET_MCUCLK_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UCHAR WMT_SET_DBGUART_REG_CMD[] = {0x01, 0x08, 0x1C, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ + ,0x30, 0x01, 0x05, 0x80/*addr:0x80050130*/ + ,0x00, 0x00, 0x00, 0x00/*value:0x00000000*/ + ,0xF0, 0x0F, 0x00, 0x00/*mask:0x00000FF0*/ + ,0x40, 0x01, 0x05, 0x80/*addr:0x80050140*/ + ,0x00, 0x01, 0x00, 0x00/*value:0x00000100*/ + ,0x00, 0x01, 0x00, 0x00/*mask:0x00000100*/ +}; +static UCHAR WMT_SET_DBGUART_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UCHAR WMT_SET_MCUIRQ_REG_CMD[] = {0x01, 0x08, (4 + 12*4), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + ,0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + ,0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + ,0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + ,0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + ,0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + ,0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + ,0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UCHAR WMT_SET_MCUIRQ_REG_CMD[] = {0x01, 0x08, (4 + 12*5), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x05 /* 5 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + ,0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + ,0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + ,0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + ,0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + ,0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + ,0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + ,0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + ,0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + ,0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + ,0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + ,0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x05 /* 5 registers */ +}; +#endif +#endif + +/* stp sdio init scripts */ +static struct init_script init_table_1_1[] = +{ + /* table_1_1 is only applied to common SDIO interface */ + INIT_CMD(WMT_SET_ALLINT_REG_CMD, WMT_SET_ALLINT_REG_EVT, "enable all interrupt"), + /* only applied to MT6620 E1/E2? */ + INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"), +}; + + +static struct init_script init_table_1_2[] = +{ + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_115200, "query baud 115200"), + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"), + INIT_CMD(WMT_SET_BAUD_CMD_X, WMT_SET_BAUD_EVT, "set baud rate"), +}; + +static struct init_script init_table_2[] = +{ + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; + +static struct init_script init_table_3[] = +{ + INIT_CMD(WMT_RESET_CMD, WMT_RESET_EVT, "wmt reset"), +#if CFG_WMT_BT_PORT2 + INIT_CMD(WMT_BTP2_CMD, WMT_BTP2_EVT, "set bt port2"), +#endif +}; + +#if 0 +static struct init_script init_table_3_1[] = +{ + INIT_CMD(WMT_WAKEUP_EN_GATE_CMD, WMT_WAKEUP_EN_GATE_EVT, "ensable gating"), +}; +#endif + +static struct init_script init_table_4[] = +{ + INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), +}; + +static struct init_script init_table_5[] = +{ + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_UART, "query stp uart"), + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; + +static struct init_script init_table_5_1[] = { + INIT_CMD(WMT_STRAP_CONF_CMD_FM_COMM, WMT_STRAP_CONF_EVT, "configure FM comm"), +}; + +static struct init_script init_table_6[] = +{ +#if 0 + INIT_CMD(WMT_SET_OSC32K_BYPASS_CMD, WMT_SET_OSC32K_BYPASS_EVT, "set OSC32k by pass mode."), +#endif + INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD,WMT_CORE_DUMP_LEVEL_04_EVT,"setup core dump level"), +}; + +#if defined(CFG_SET_OPT_REG) && CFG_SET_OPT_REG +static struct init_script set_registers[] = +{ + //INIT_CMD(WMT_SET_GPS_REG_CMD, WMT_SET_GPS_REG_EVT, "set wmt registers"), + //INIT_CMD(WMT_SET_SDIODRV_REG_CMD, WMT_SET_SDIODRV_REG_EVT, "set SDIO driving registers") + #if CFG_WMT_I2S_DBGUART_SUPPORT + INIT_CMD(WMT_SET_DBGUART_REG_CMD, WMT_SET_DBGUART_REG_EVT, "set debug uart registers"), + #endif + #if CFG_SET_OPT_REG_SWLA + INIT_CMD(WMT_SET_SWLA_REG_CMD, WMT_SET_SWLA_REG_EVT, "set swla registers"), + #endif + #if CFG_SET_OPT_REG_MCUCLK + INIT_CMD(WMT_SET_MCUCLK_REG_CMD, WMT_SET_MCUCLK_REG_EVT, "set mcuclk dbg registers"), + #endif + #if CFG_SET_OPT_REG_MCUIRQ + INIT_CMD(WMT_SET_MCUIRQ_REG_CMD, WMT_SET_MCUIRQ_REG_EVT, "set mcu irq dbg registers"), + #endif +}; +#endif + +static struct init_script coex_table[] = { + INIT_CMD(WMT_COEX_SETTING_CONFIG_CMD, WMT_COEX_SETTING_CONFIG_EVT, "coex_wmt"), + INIT_CMD(WMT_BT_COEX_SETTING_CONFIG_CMD, WMT_BT_COEX_SETTING_CONFIG_EVT, "coex_bt"), + INIT_CMD(WMT_WIFI_COEX_SETTING_CONFIG_CMD, WMT_WIFI_COEX_SETTING_CONFIG_EVT, "coex_wifi"), + INIT_CMD(WMT_PTA_COEX_SETTING_CONFIG_CMD, WMT_PTA_COEX_SETTING_CONFIG_EVT, "coex_ext_pta"), + INIT_CMD(WMT_MISC_COEX_SETTING_CONFIG_CMD, WMT_MISC_COEX_SETTING_CONFIG_EVT, "coex_misc"), +}; + +/* MT6620 Chip Version and Info Table */ +static const WMT_IC_INFO_S mt6620_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_NO_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E1, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_FALSE, + }, + { + .u4HwVer = 0x8A01, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_NO_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E2, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_FALSE, + }, + { + .u4HwVer = 0x8A10, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E3_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E3, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A11, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E4, + .cPatchNameExt = WMT_IC_PATCH_E3_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E4, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A30, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E6, + .cPatchNameExt = WMT_IC_PATCH_E6_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E6, + .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*MTK_WCN_BOOL_FALSE*/, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B30, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E6, + .cPatchNameExt = WMT_IC_PATCH_E6_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E6, + .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*MTK_WCN_BOOL_FALSE*/, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B31, + .cChipName = WMT_IC_NAME_MT6620, + .cChipVersion = WMT_IC_VER_E7, + .cPatchNameExt = WMT_IC_PATCH_E6_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E7, + .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*MTK_WCN_BOOL_FALSE*/, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 +mt6620_sw_init ( + P_WMT_HIF_CONF pWmtHifConf + ); + +static INT32 +mt6620_sw_deinit ( + P_WMT_HIF_CONF pWmtHifConf + ); + +static INT32 +mt6620_pin_ctrl ( + WMT_IC_PIN_ID id, + WMT_IC_PIN_STATE state, + UINT32 flag + ); + +static INT32 +mt6620_aif_ctrl ( + WMT_IC_PIN_STATE state, + UINT32 flag + ); + +static INT32 +mt6620_ver_check (VOID); + +static const WMT_IC_INFO_S* +mt6620_find_wmt_ic_info ( + const UINT32 hw_ver + ); + +static INT32 +wmt_stp_init_coex (VOID); + +#if CFG_WMT_MULTI_PATCH +static INT32 +mt6620_patch_dwn (UINT32 index); +static INT32 mt6620_patch_info_prepare(VOID); +#else +static INT32 +mt6620_update_patch_name (VOID); + +static INT32 +mt6620_patch_dwn (VOID); +#endif +static MTK_WCN_BOOL mt6620_quick_sleep_flag_get(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* MT6620 Operation Function Table */ +const WMT_IC_OPS wmt_ic_ops_mt6620 = { + .icId = 0x6620, + .sw_init = mt6620_sw_init, + .sw_deinit = mt6620_sw_deinit, + .ic_pin_ctrl = mt6620_pin_ctrl, + .ic_ver_check = mt6620_ver_check, + .co_clock_ctrl = NULL, + .is_quick_sleep = mt6620_quick_sleep_flag_get, + .is_aee_dump_support = NULL, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +static INT32 +mt6620_sw_init ( + P_WMT_HIF_CONF pWmtHifConf + ) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + UCHAR evtBuf[256]; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + UINT32 hw_ver; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(NULL != gp_mt6620_info); + if ( (NULL == gp_mt6620_info) + || (NULL == pWmtHifConf) + ) { + WMT_ERR_FUNC("null pointers: gp_mt6620_info(0x%p), pWmtHifConf(0x%p)\n", + gp_mt6620_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_mt6620_info->u4HwVer; + + //4 <3.1> start init for sdio + if (WMT_HIF_SDIO == pWmtHifConf->hifType) { + /* 1. enable all INT32 */ + /* 2. disable mcu gate (only MT6620E1/E2) */ + iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet); + osal_assert(0); + return -1; + } + } + + //4 <3.2> start init for uart + if (WMT_HIF_UART == pWmtHifConf->hifType) { + /* init variable fields for script execution */ + osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//0xC0 MTK Flow Control /* no flow control */ + osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //0xC0 MTK Flow Control /* no flow control */ + + /* 3. Query chip baud rate (TEST-ONLY) */ + /* 4. Query chip STP options (TEST-ONLY) */ + /* 5. Change chip baud rate: t_baud */ + //WMT_DBG_FUNC("WMT-CORE: init_table_1_2 set chip baud:%d", pWmtHifConf->au4HifConf[0]); + iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); + osal_assert(0); + return -2; + } + + /* 6. Set host baudrate and flow control*/ + ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet); + return -3; + } + WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]); + + /* 7. Wake up chip and check event */ +// iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res); + iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != 1)) { + WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res); + return -4; + } + + osal_memset(evtBuf, 0, osal_sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res); +#ifdef CFG_DUMP_EVT + WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n", + (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); +#endif + if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) { + WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet); + return -5; + } + //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok"); + +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n"); + return -6; + } +#endif + + /* 8. Query baud rate (TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet); + return -7; + } + } + + /* 9. download patch */ + iRet = mt6620_patch_dwn(); + + WMT_INFO_FUNC("Not to check the patch validity\n"); +#if 0 + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d)\n", iRet); + return -8; + } + else { + WMT_INFO_FUNC("patch dwn ok\n"); + } +#endif + /* 10. WMT Reset command */ + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -9; + } + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + else { + WMT_INFO_FUNC("init_coex ok\n"); + } + +#if 0 + /*10-2 enable 32K By Pass Mode*/ + //if hwVer = E3/E4, please enable 32K by pass mode. + //does not support mt6620E1/E2, always enable 32k bypass mode + //if ((hwVer == 0x8a10 || hwVer == 0x8a11)) + { + WMT_INFO_FUNC("WMT-CORE: init_table_6 OSC32K"); + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet == 0) { + WMT_DBG_FUNC("WMT-CORE: init_table_6 OSC32K, successful\n"); + } + else { + WMT_WARN_FUNC("init table 6 OSC32K fail, continue init...\n"); + /*return -11;*/ + } + } +#endif + + if (WMT_HIF_UART == pWmtHifConf->hifType) { + /* 11. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); + if (iRet) { + WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); + return -12; + } + + /* 12. Enable host STP-UART mode */ + ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_FULL_MODE; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("enable host STP-UART-FULL mode fail(%d)\n", iRet); + return -13; + } + WMT_INFO_FUNC("enable host STP-UART-FULL mode\n"); + /*13. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/ + osal_msleep(10); + /* 14. Query chip STP options (TEST-ONLY) */ + /* 15. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -14; + } + } + + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", + pWmtHifConf->au4StrapConf[0], + iRet); + return -15; + } + WMT_INFO_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); + +#if CFG_SET_OPT_REG /*set registers*/ + iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); + if (iRet) { + WMT_ERR_FUNC("set_registers fail(%d)", iRet); + return -16; + } +#endif + +#if 0 + /* 16. trace32 dump when fw assert*/ + { + INT32 val = 0x00000001; + WMT_INFO_FUNC("WMT-CORE: enable assert dump"); + wmt_reg_rw_raw(1, 0x0100092c, &val, 0xFFFFFFFF); + } +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_mt6620_info); + if (NULL != gp_mt6620_info) { + if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) { + wmt_lib_ps_enable(); + } + else { + wmt_lib_ps_disable(); + } + } +#endif + + return 0; +} +#endif + +static INT32 +mt6620_sw_init ( + P_WMT_HIF_CONF pWmtHifConf + ) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + UCHAR evtBuf[256]; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + UINT32 hw_ver; + UINT32 patch_num = 0; + UINT32 patch_index = 0; + WMT_DBG_FUNC(" start\n"); + + osal_assert(NULL != gp_mt6620_info); + if ( (NULL == gp_mt6620_info) + || (NULL == pWmtHifConf) + ) { + WMT_ERR_FUNC("null pointers: gp_mt6620_info(0x%p), pWmtHifConf(0x%p)\n", + gp_mt6620_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_mt6620_info->u4HwVer; + + //4 <3.1> start init for sdio + if (WMT_HIF_SDIO == pWmtHifConf->hifType) { + /* 1. enable all INT32 */ + /* 2. disable mcu gate (only MT6620E1/E2) */ + iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet); + osal_assert(0); + return -1; + } + } + + //4 <3.2> start init for uart + if (WMT_HIF_UART == pWmtHifConf->hifType) { + + /* init variable fields for script execution */ + osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + if (WMT_UART_MTK_SW_FC == pWmtHifConf->uartFcCtrl) + { + WMT_INFO_FUNC("enable MTK SW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x80;//* MTK SW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x80; //* MTK SW flow control */ + } + else if (WMT_UART_LUX_SW_FC == pWmtHifConf->uartFcCtrl) + { + WMT_INFO_FUNC("enable Linux SW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x80;//* Linux SW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x80; //* Linux SW flow control */ + } + else if (WMT_UART_HW_FC == pWmtHifConf->uartFcCtrl) + { + WMT_INFO_FUNC("enable HW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0xC0;//* HW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0xC0; //* HW flow control */ + } + else { + /* WMT_UART_NO_FC and all other cases!!! */ + WMT_INFO_FUNC("no Flow Control (uartFcCtrl:%d)\n", pWmtHifConf->uartFcCtrl); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//* no flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //* no flow control */ + } + + /* 3. Query chip baud rate (TEST-ONLY) */ + /* 4. Query chip STP options (TEST-ONLY) */ + /* 5. Change chip baud rate: t_baud */ + //WMT_DBG_FUNC("WMT-CORE: init_table_1_2 set chip baud:%d", pWmtHifConf->au4HifConf[0]); + iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); + osal_assert(0); + return -2; + } + + /* 6. Set host baudrate and flow control*/ + ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet); + return -3; + } + WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]); + + /* 7. Wake up chip and check event */ +// iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res); + iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != 1)) { + WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res); + return -4; + } + + osal_memset(evtBuf, 0, osal_sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res); +#ifdef CFG_DUMP_EVT + WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n", + (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); +#endif + if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) { + WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet); + return -5; + } + //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok"); + +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n"); + return -6; + } +#endif + + /* 8. Query baud rate (TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet); + return -7; + } + } + if (WMT_HIF_UART == pWmtHifConf->hifType) { + /* 9. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); + if (iRet) { + WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); + return -8; + } + + /* 10. Enable host STP-UART mode */ + ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_FULL_MODE; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("enable host STP-UART-FULL mode fail(%d)\n", iRet); + return -9; + } + WMT_INFO_FUNC("enable host STP-UART-FULL mode\n"); + /*10. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/ + osal_msleep(10); + /* 11. Query chip STP options (TEST-ONLY) */ + /* 12. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -10; + } + } + /* 13. download patch */ +#if CFG_WMT_MULTI_PATCH + iRet = mt6620_patch_info_prepare(); + if(iRet) + { + WMT_ERR_FUNC("patch info perpare fail(%d)\n",iRet); + return -11; + } + + ctrlPa1 = 0;ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM,&ctrlPa1,&ctrlPa2); + patch_num = ctrlPa1; + WMT_INFO_FUNC("patch total num = [%d]\n",patch_num); + + for(patch_index = 0;patch_index < patch_num;patch_index++) + { + iRet = mt6620_patch_dwn(patch_index); + if(iRet){ + WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet,patch_index); + return -12; + } + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -13; + } + } +#else + iRet = mt6620_patch_dwn(); + + WMT_INFO_FUNC("Not to check the patch validity\n"); +#if 0 + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d)\n", iRet); + return -11; + } + else { + WMT_INFO_FUNC("patch dwn ok\n"); + } +#endif + /* 14. WMT Reset command */ + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -13; + } +#endif + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -14; + } + else { + WMT_INFO_FUNC("init_coex ok\n"); + } + +#if 0 + /*10-2 enable 32K By Pass Mode*/ + //if hwVer = E3/E4, please enable 32K by pass mode. + //does not support mt6620E1/E2, always enable 32k bypass mode + //if ((hwVer == 0x8a10 || hwVer == 0x8a11)) + { + WMT_INFO_FUNC("WMT-CORE: init_table_6 OSC32K"); + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet == 0) { + WMT_DBG_FUNC("WMT-CORE: init_table_6 OSC32K, successful\n"); + } + else { + WMT_WARN_FUNC("init table 6 OSC32K fail, continue init...\n"); + /*return -14;*/ + } + } +#endif + + + + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", + pWmtHifConf->au4StrapConf[0], + iRet); + return -15; + } + WMT_INFO_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); + +#if CFG_SET_OPT_REG /*set registers*/ + iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); + if (iRet) { + WMT_ERR_FUNC("set_registers fail(%d)", iRet); + return -16; + } +#endif + +#if 0 + /* 16. trace32 dump when fw assert*/ + { + INT32 val = 0x00000001; + WMT_INFO_FUNC("WMT-CORE: enable assert dump"); + wmt_reg_rw_raw(1, 0x0100092c, &val, 0xFFFFFFFF); + } +#endif + +#if CFG_WMT_COREDUMP_ENABLE + /*Open Core Dump Function @QC begin*/ + mtk_wcn_stp_coredump_flag_ctrl(1); +#endif + if (0 != mtk_wcn_stp_coredump_flag_get()) + { + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", + iRet); + return -17; + } else { + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } + } + else + { + WMT_INFO_FUNC("disable mt662x firmware coredump\n"); + } + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_mt6620_info); + if (NULL != gp_mt6620_info) { + if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) { + wmt_lib_ps_enable(); + } + else { + wmt_lib_ps_disable(); + } + } +#endif + + return 0; +} + + +static INT32 +mt6620_sw_deinit ( + P_WMT_HIF_CONF pWmtHifConf + ) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_mt6620_info); + if ( (NULL != gp_mt6620_info) + && (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) ) { + wmt_lib_ps_disable(); + } +#endif + + gp_mt6620_info = NULL; + + return 0; +} + +static INT32 +mt6620_aif_ctrl ( + WMT_IC_PIN_STATE state, + UINT32 flag + ) +{ + INT32 ret = -1; + UINT32 val; + + if ( (flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE ) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000710; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + default: + WMT_ERR_FUNC("unsupported state (%d) \n", state); + ret = -1; + break; + } + } + else { + /*PCM & I2S separate*/ + WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n"); + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000070; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + case WMT_IC_AIF_3: + val = 0x00000000; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + default: + WMT_ERR_FUNC("unsupported state (%d) \n", state); + ret = -1; + break; + } + } + + if (!ret) { + WMT_INFO_FUNC("new state(%d) ok\n", state); + } + else { + WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret); + } + + return ret; +} + +static INT32 +mt6620_pin_ctrl ( + WMT_IC_PIN_ID id, + WMT_IC_PIN_STATE state, + UINT32 flag + ) +{ + INT32 ret; + + WMT_DBG_FUNC("ic pin id:%d, state:%d, flag:0x%x\n", id , state, flag); + + ret = -1; + switch (id) { + case WMT_IC_PIN_AUDIO: + ret = mt6620_aif_ctrl(state, flag); + break; + + case WMT_IC_PIN_EEDI: + WMT_WARN_FUNC("TBD!!"); + ret = -1; + break; + + case WMT_IC_PIN_EEDO: + WMT_WARN_FUNC("TBD!!"); + ret = -1; + break; + case WMT_IC_PIN_GSYNC: + ret = -1; + WMT_WARN_FUNC("TBD!!"); + break; + default: + break; + } + WMT_INFO_FUNC("ret = (%d)\n" , ret); + + return ret; +} + + +static MTK_WCN_BOOL mt6620_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_FALSE; +} + + + +static INT32 +mt6620_ver_check (VOID) +{ + UINT32 hw_ver; + UINT32 fw_ver; + INT32 iret; + const WMT_IC_INFO_S *p_info; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("MT6620: before read hw_ver (hw version)\n"); + iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("MT6620: read hw_ver fail:%d\n", iret); + return -2; + } + WMT_INFO_FUNC("MT6620: read hw_ver (hw version) (0x%x)\n", hw_ver); + + WMT_LOUD_FUNC("MT6620: before fw_ver (rom version) \n"); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("MT6620: read fw_ver fail:%d\n", iret); + return -2; + } + WMT_INFO_FUNC("MT6620: read fw_ver (rom version) (0x%x)\n", fw_ver); + + p_info = mt6620_find_wmt_ic_info(hw_ver); + if (NULL == p_info) { + WMT_ERR_FUNC("MT6620: hw_ver(0x%x) find wmt ic info fail\n"); + return -3; + } + + WMT_INFO_FUNC("MT6620: wmt ic info: %s.%s (0x%x, WMTHWVER:%d, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->eWmtHwVer, + p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006620UL << 16) | (hw_ver & 0x0000FFFF); + /* translated hw version & fw rom version */ + ctrlPa2 = ((UINT32)(p_info->eWmtHwVer) << 16) | (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + if (iret) { + WMT_WARN_FUNC("MT6620: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret); + } + + gp_mt6620_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S* +mt6620_find_wmt_ic_info ( + const UINT32 hw_ver + ) +{ + /* match chipversion with u4HwVer item in mt6620_info_table */ + const UINT32 size = osal_array_size(mt6620_info_table); + INT32 index; + + /* George: reverse the search order to favor newer version products */ + // TODO:[FixMe][GeorgeKuo] Remove full match once API wmt_lib_get_hwver() is changed correctly in the future!! + // Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. + index = size - 1; + /* full match */ + while ( (0 <= index) + && (hw_ver != mt6620_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + if (0 <= index) { + WMT_INFO_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mt6620_info_table[index]; + } + + WMT_WARN_FUNC("find no ic info for (0x%x) by full match!try major num match!\n", hw_ver); + + /* George: The ONLY CORRECT method to find supported hw table. Match MAJOR + * NUM only can help us support future minor hw ECO, or fab switch, etc. + * FULL matching eliminate such flexibility and software package have to be + * updated EACH TIME even when minor hw ECO or fab switch!!! + */ + /* George: reverse the search order to favor newer version products */ + index = size - 1; + /* major num match */ + while ( (0 <= index) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6620_info_table[index].u4HwVer)) + ) { + --index; + } + if (0 <= index) { + WMT_INFO_FUNC("MT6620: found ic info for hw_ver(0x%x) by major num! index:%d\n", hw_ver, index); + return &mt6620_info_table[index]; + } + + WMT_ERR_FUNC("MT6620: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", hw_ver); + return NULL; +} + + +static INT32 +wmt_stp_init_coex (VOID) +{ + INT32 iRet; + UINT32 addr; + WMT_GEN_CONF *pWmtGenConf; + + #define COEX_WMT 0 + #define COEX_BT 1 + #define COEX_WIFI 2 + #define COEX_PTA 3 + #define COEX_MISC 4 + + /*Get wmt config*/ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF)addr; + + /*Check if WMT.cfg exists*/ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value*/ + return 0; + } + + /*Dump the coex-related info*/ + WMT_DBG_FUNC("coex_wmt:0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_wmt_ant_mode, + pWmtGenConf->coex_wmt_wifi_time_ctl, + pWmtGenConf->coex_wmt_ext_pta_dev_on + ); + WMT_DBG_FUNC("coex_bt:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_bt_rssi_upper_limit, + pWmtGenConf->coex_bt_rssi_mid_limit, + pWmtGenConf->coex_bt_rssi_lower_limit, + pWmtGenConf->coex_bt_pwr_high, + pWmtGenConf->coex_bt_pwr_mid, + pWmtGenConf->coex_bt_pwr_low + ); + WMT_DBG_FUNC("coex_wifi:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_wifi_rssi_upper_limit, + pWmtGenConf->coex_wifi_rssi_mid_limit, + pWmtGenConf->coex_wifi_rssi_lower_limit, + pWmtGenConf->coex_wifi_pwr_high, + pWmtGenConf->coex_wifi_pwr_mid, + pWmtGenConf->coex_wifi_pwr_low + ); + WMT_DBG_FUNC("coex_ext_pta:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_ext_pta_hi_tx_tag, + pWmtGenConf->coex_ext_pta_hi_rx_tag, + pWmtGenConf->coex_ext_pta_lo_tx_tag, + pWmtGenConf->coex_ext_pta_lo_rx_tag, + pWmtGenConf->coex_ext_pta_sample_t1, + pWmtGenConf->coex_ext_pta_sample_t2, + pWmtGenConf->coex_ext_pta_wifi_bt_con_trx + ); + WMT_DBG_FUNC("coex_misc:0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_misc_ext_pta_on, + pWmtGenConf->coex_misc_ext_feature_set + ); + + /*command adjustion due to WMT.cfg*/ + coex_table[COEX_WMT].cmd[5]= pWmtGenConf->coex_wmt_ant_mode; + coex_table[COEX_WMT].cmd[6]= pWmtGenConf->coex_wmt_wifi_time_ctl; + coex_table[COEX_WMT].cmd[7]= pWmtGenConf->coex_wmt_ext_pta_dev_on; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WMT].cmd[0], + coex_table[COEX_WMT].str, + coex_table[COEX_WMT].cmdSz); + } + + coex_table[COEX_BT].cmd[9]= pWmtGenConf->coex_bt_rssi_upper_limit; + coex_table[COEX_BT].cmd[10]= pWmtGenConf->coex_bt_rssi_mid_limit; + coex_table[COEX_BT].cmd[11]= pWmtGenConf->coex_bt_rssi_lower_limit; + coex_table[COEX_BT].cmd[12]= pWmtGenConf->coex_bt_pwr_high; + coex_table[COEX_BT].cmd[13]= pWmtGenConf->coex_bt_pwr_mid; + coex_table[COEX_BT].cmd[14]= pWmtGenConf->coex_bt_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_BT].cmd[0], + coex_table[COEX_BT].str, + coex_table[COEX_BT].cmdSz); + } + coex_table[COEX_WIFI].cmd[10]= pWmtGenConf->coex_wifi_rssi_upper_limit; + coex_table[COEX_WIFI].cmd[11]= pWmtGenConf->coex_wifi_rssi_mid_limit; + coex_table[COEX_WIFI].cmd[12]= pWmtGenConf->coex_wifi_rssi_lower_limit; + coex_table[COEX_WIFI].cmd[13]= pWmtGenConf->coex_wifi_pwr_high; + coex_table[COEX_WIFI].cmd[14]= pWmtGenConf->coex_wifi_pwr_mid; + coex_table[COEX_WIFI].cmd[15]= pWmtGenConf->coex_wifi_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WIFI].cmd[0], + coex_table[COEX_WIFI].str, + coex_table[COEX_WIFI].cmdSz); + } + coex_table[COEX_PTA].cmd[5]= pWmtGenConf->coex_ext_pta_hi_tx_tag; + coex_table[COEX_PTA].cmd[6]= pWmtGenConf->coex_ext_pta_hi_rx_tag; + coex_table[COEX_PTA].cmd[7]= pWmtGenConf->coex_ext_pta_lo_tx_tag; + coex_table[COEX_PTA].cmd[8]= pWmtGenConf->coex_ext_pta_lo_rx_tag; + coex_table[COEX_PTA].cmd[9]= ((pWmtGenConf->coex_ext_pta_sample_t1 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[10]= ((pWmtGenConf->coex_ext_pta_sample_t1 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[11]= ((pWmtGenConf->coex_ext_pta_sample_t2 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[12]= ((pWmtGenConf->coex_ext_pta_sample_t2 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[13]= pWmtGenConf->coex_ext_pta_wifi_bt_con_trx; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_PTA].cmd[0], + coex_table[COEX_PTA].str, + coex_table[COEX_PTA].cmdSz); + } + + osal_memcpy(&coex_table[COEX_MISC].cmd[5], &pWmtGenConf->coex_misc_ext_pta_on, sizeof(pWmtGenConf->coex_misc_ext_pta_on)); + osal_memcpy(&coex_table[COEX_MISC].cmd[9], &pWmtGenConf->coex_misc_ext_feature_set, sizeof(pWmtGenConf->coex_misc_ext_feature_set)); + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(& coex_table[COEX_MISC].cmd[0], coex_table[COEX_MISC].str, coex_table[COEX_MISC].cmdSz); + } + iRet = wmt_core_init_script(coex_table, sizeof(coex_table)/sizeof(coex_table[0])); + + return iRet; +} + +#if CFG_WMT_MULTI_PATCH + +static INT32 mt6620_patch_info_prepare(VOID) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + + return iRet; +} +static INT32 +mt6620_patch_dwn (UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr = NULL; + PUINT8 pbuf = NULL; + UINT32 patchSize = 0; + UINT32 fragSeq = 0; + UINT32 fragNum = 0; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 patchevtBuf[8]; + UINT8 addressevtBuf[12]; + UCHAR addressByte[4]; + PCHAR cDataTime = NULL; + /*PCHAR cPlat = NULL;*/ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_mt6620_info) { + WMT_ERR_FUNC("null gp_mt6620_info!\n"); + return -1; + } + + osal_memset(gFullPatchName,0,osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + ctrlData.au4CtrlData[2] = (UINT32)&addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_INFO_FUNC("the %d time valid patch found: (%s)\n", index+1,gFullPatchName); + //<2.2> read patch content + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32)NULL; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + + ctrlData.au4CtrlData[2] = (UINT32)&pbuf; + ctrlData.au4CtrlData[3] = (UINT32)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d \n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH)pbuf; + // check patch file information + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0];*/ + cDataTime[15] = '\0'; + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + + if(index == 0) + { + WMT_INFO_FUNC("===========================================\n"); + WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime); + WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n", ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], + patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_INFO_FUNC("[Combo Patch] Content Size = 0x%x\n", patchSize); + WMT_INFO_FUNC("[Combo Patch] Content CRC = 0x%04x\n", osal_crc16(pbuf, patchSize)); + WMT_INFO_FUNC("===========================================\n"); + } + + patchSizePerFrag = (MAJORNUM(gp_mt6620_info->u4HwVer) != 0) ? + DEFAULT_PATCH_FRAG_SIZE : MT6620E2_PATCH_FRAG_SIZE; + + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + /*send wmt part patch address command*/ + iRet = wmt_core_tx((PUINT8)&WMT_PATCH_ADDRESS_CMD[0],sizeof(WMT_PATCH_ADDRESS_CMD),&u4Res,MTK_WCN_BOOL_FALSE); + if(iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_CMD))) + { + WMT_ERR_FUNC("wmt_core:wmt patch address CMD fail(%d),size(%d)\n",iRet,u4Res); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf,0,sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf,sizeof(WMT_PATCH_ADDRESS_EVT),&u4Res); + if(iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT))) + { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d)\n",iRet,u4Res); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail\n"); + iRet -= 1; + goto done; + } +#endif + + /*send part patch address command*/ + osal_memcpy(&WMT_PATCH_P_ADDRESS_CMD[12], addressByte,osal_sizeof(addressByte)); + WMT_INFO_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x",WMT_PATCH_P_ADDRESS_CMD[12],WMT_PATCH_P_ADDRESS_CMD[13],WMT_PATCH_P_ADDRESS_CMD[14],WMT_PATCH_P_ADDRESS_CMD[15]); + iRet = wmt_core_tx((PUINT8)&WMT_PATCH_P_ADDRESS_CMD[0],sizeof(WMT_PATCH_P_ADDRESS_CMD),&u4Res,MTK_WCN_BOOL_FALSE); + if(iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_CMD))) + { + WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d),index(%d)\n",iRet,u4Res,index); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf,0,sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf,sizeof(WMT_PATCH_P_ADDRESS_EVT),&u4Res); + if(iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_EVT))) + { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d),index(%d)\n",iRet,u4Res,index); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_P_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail,index(%d)\n",index); + iRet -= 1; + goto done; + } +#endif + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum-1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } + else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST: WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag*/ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + //iRet = (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res); + iRet = wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet ); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(patchevtBuf, 0, sizeof(patchevtBuf)); + //iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + iRet = wmt_core_rx(patchevtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(patchevtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT result error rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, patchevtBuf[0], patchevtBuf[1], patchevtBuf[2], patchevtBuf[3], patchevtBuf[4], sizeof(WMT_PATCH_EVT), WMT_PATCH_EVT[0], WMT_PATCH_EVT[1], WMT_PATCH_EVT[2], WMT_PATCH_EVT[3], WMT_PATCH_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", + sizeof(WMT_PATCH_EVT), u4Res); + +#if 0 + WMT_DBG_FUNC("wmt_core: send patch frag(%d) [%02X,%02X,%02X,%02X,%02X] (%d) ok", + fragSeq, WMT_PATCH_CMD[0], WMT_PATCH_CMD[1], WMT_PATCH_CMD[2], + WMT_PATCH_CMD[3], WMT_PATCH_CMD[4], fragSize); +#endif + + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail"); + + if (fragSeq != fragNum) { + iRet = -7; + } +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; + ctrlData.au4CtrlData[0] = index + 1; + wmt_ctrl(&ctrlData); + //wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + if ( (iRet == -2) || (iRet == -3) ) { + /*no patch found or patch version does not match with hw version, we check if patch is mandatory or not, if yes, return iRet, if not return 0*/ + if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bWorkWithoutPatch) { + iRet = 0; + } + } + + return iRet; +} + + +#else +static INT32 +mt6620_patch_dwn (VOID) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + PCHAR cDataTime = NULL; + /*PCHAR cPlat = NULL;*/ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_mt6620_info) { + WMT_ERR_FUNC("null gp_mt6620_info!\n"); + return -1; + } +#if 0 + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (UINT32)&gDefPatchName; + iRet = wmt_ctrl(&ctrlData); + + if (mt6620_update_patch_name()) { + WMT_ERR_FUNC("invalid patch name, ommit patch download process.\n"); + return -1; + } + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32)&gDefPatchName; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + ctrlData.au4CtrlData[2] = (UINT32)&pbuf; + ctrlData.au4CtrlData[3] = (UINT32)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d \n", iRet); + iRet = -2; + goto done; + } +#else + //<2> search patch and read patch content + //<2.1> search patch + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + if (0 == iRet) + { + //patch with correct Hw Ver Major Num found + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (UINT32)&gFullPatchName; + iRet = wmt_ctrl(&ctrlData); + + WMT_INFO_FUNC("valid patch found: (%s)\n", gFullPatchName); + //<2.2> read patch content + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32)NULL; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + + } + else + { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (UINT32)&pbuf; + ctrlData.au4CtrlData[3] = (UINT32)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d \n", iRet); + iRet -= 1; + goto done; + } + +#endif + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH)pbuf; + // check patch file information + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0];*/ + + cDataTime[15] = '\0'; + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + WMT_INFO_FUNC("===========================================\n"); + WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime); + WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n", ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], + patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_INFO_FUNC("[Combo Patch] Content Size = 0x%x\n", patchSize); + WMT_INFO_FUNC("[Combo Patch] Content CRC = 0x%04x\n", osal_crc16(pbuf, patchSize)); + WMT_INFO_FUNC("===========================================\n"); + + patchSizePerFrag = (MAJORNUM(gp_mt6620_info->u4HwVer) != 0) ? + DEFAULT_PATCH_FRAG_SIZE : MT6620E2_PATCH_FRAG_SIZE; + + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum-1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } + else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST: WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag*/ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + //iRet = (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res); + iRet = wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet ); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + //iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT result error rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], sizeof(WMT_PATCH_EVT), WMT_PATCH_EVT[0], WMT_PATCH_EVT[1], WMT_PATCH_EVT[2], WMT_PATCH_EVT[3], WMT_PATCH_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", + sizeof(WMT_PATCH_EVT), u4Res); + +#if 0 + WMT_DBG_FUNC("wmt_core: send patch frag(%d) [%02X,%02X,%02X,%02X,%02X] (%d) ok", + fragSeq, WMT_PATCH_CMD[0], WMT_PATCH_CMD[1], WMT_PATCH_CMD[2], + WMT_PATCH_CMD[3], WMT_PATCH_CMD[4], fragSize); +#endif + + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail"); + + if (fragSeq != fragNum) { + iRet = -7; + } +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + if ( (iRet == -2) || (iRet == -3) ) { + /*no patch found or patch version does not match with hw version, we check if patch is mandatory or not, if yes, return iRet, if not return 0*/ + if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bWorkWithoutPatch) { + iRet = 0; + } + } + + return iRet; +} + +static INT32 +mt6620_update_patch_name (VOID) +{ + INT32 len; + UCHAR cTmpPatchName[NAME_MAX + 1] = {0}; + + /*init.get hardware version */ + // TODO:[FixMe][GeorgeKuo]: check using memcpy or strncpy??? + /*osal_memcpy (gFullPatchName, gDefPatchName, osal_strlen(gDefPatchName));*/ + osal_strncpy(gFullPatchName, gDefPatchName, osal_sizeof(gFullPatchName)); + + /*1.check hardware information */ + if (NULL == gp_mt6620_info) { + WMT_ERR_FUNC("null gp_mt6620_info!\n"); + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + return -1; + } + + /*2.make possible firmware patch name with original name and hardware version*/ + if ( (osal_strlen(gDefPatchName) > osal_strlen(WMT_IC_PATCH_TAIL)) + && ((osal_strlen(gDefPatchName) + osal_strlen(WMT_IC_PATCH_DUMMY_EXT) <= NAME_MAX)) + ) { + len = osal_strlen(gDefPatchName) - osal_strlen(WMT_IC_PATCH_TAIL); + osal_memcpy (cTmpPatchName, gDefPatchName, len > NAME_MAX ? NAME_MAX : len); + osal_memcpy (cTmpPatchName + osal_strlen(cTmpPatchName), gp_mt6620_info->cPatchNameExt, osal_strlen(gp_mt6620_info->cPatchNameExt)); + osal_memcpy (cTmpPatchName + osal_strlen(cTmpPatchName), WMT_IC_PATCH_TAIL, osal_strlen(WMT_IC_PATCH_TAIL)); + cTmpPatchName[osal_strlen(cTmpPatchName)] = '\0'; + } + else { + WMT_ERR_FUNC("invalid default firmware patch name (%s)\n", gDefPatchName); + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + return -2; + } + + /*patch with versioned name exist , update cFullPatchName with full named patch*/ + osal_memcpy (gFullPatchName, cTmpPatchName, osal_strlen(cTmpPatchName)); + *(gFullPatchName + osal_strlen(cTmpPatchName)) = '\0'; + WMT_INFO_FUNC("full firmware patch name: %s\n", cTmpPatchName); + + return 0; +} +#endif + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c b/drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c new file mode 100755 index 000000000000..0b966fea4727 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c @@ -0,0 +1,1959 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-IC]" +#define CFG_IC_MT6628 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +#define CFG_WMT_BT_PORT2 (0) /* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC,*/ + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UCHAR gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6628_info = NULL; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; +#if 0 +static UCHAR WMT_WAKEUP_DIS_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x04}; +static UCHAR WMT_WAKEUP_DIS_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x04}; + +static UCHAR WMT_WAKEUP_EN_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x05}; +static UCHAR WMT_WAKEUP_EN_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x05}; +#endif + +static UCHAR WMT_QUERY_BAUD_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x02}; +static UCHAR WMT_QUERY_BAUD_EVT_115200[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00}; +static UCHAR WMT_QUERY_BAUD_EVT_X[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB}; +static UCHAR WMT_QUERY_STP_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x04}; +static UCHAR WMT_QUERY_STP_EVT_DEFAULT[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00}; +static UCHAR WMT_QUERY_STP_EVT_UART[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01}; +static UCHAR WMT_SET_BAUD_CMD_X[] = {0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB}; +static UCHAR WMT_SET_BAUD_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x01}; +static UCHAR WMT_SET_WAKEUP_WAKE_CMD_RAW[] = {0xFF}; +static UCHAR WMT_SET_WAKEUP_WAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03}; +static UCHAR WMT_PATCH_CMD[] = {0x01, 0x01, 0x00, 0x00, 0x00}; +static UCHAR WMT_PATCH_EVT[] = {0x02, 0x01, 0x01, 0x00, 0x00}; +static UCHAR WMT_RESET_CMD[] = {0x01, 0x07, 0x01, 0x00, 0x04}; +static UCHAR WMT_RESET_EVT[] = {0x02, 0x07, 0x01, 0x00, 0x00}; +#if CFG_WMT_BT_PORT2 +static UCHAR WMT_BTP2_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01}; +static UCHAR WMT_BTP2_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +#endif + +#if CFG_WMT_MULTI_PATCH +static UCHAR WMT_PATCH_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0xD4,0x01,0x09,0xF0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff}; +static UCHAR WMT_PATCH_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01}; +static UCHAR WMT_PATCH_P_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x48,0x03,0x09,0xF0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff}; +static UCHAR WMT_PATCH_P_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01}; +#endif + +/*coex cmd/evt++*/ +static UCHAR WMT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x02, 0x00, 0x01, 0x00}; +static UCHAR WMT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; + +#if CFG_SUBSYS_COEX_NEED +static UCHAR WMT_BT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB,0xCC,0xDD,0xEE,0xFF,0xAA}; +static UCHAR WMT_BT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00,0x00,0x00,0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA}; +static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_PTA_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE}; +static UCHAR WMT_PTA_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +static UCHAR WMT_MISC_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB}; +static UCHAR WMT_MISC_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00}; +#endif + +/*coex cmd/evt--*/ +static UCHAR WMT_SET_STP_CMD[] = {0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01}; +static UCHAR WMT_SET_STP_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x03}; +static UCHAR WMT_STRAP_CONF_CMD_FM_COMM[] = {0x01, 0x05, 0x02, 0x00, 0x02, 0x02}; +static UCHAR WMT_STRAP_CONF_EVT[] = {0x02, 0x05, 0x02, 0x00, 0x00, 0x02}; +#if 0 +static UCHAR WMT_SET_OSC32K_BYPASS_CMD[]= {0x01, 0x0A, 0x01, 0x00, 0x05}; +static UCHAR WMT_SET_OSC32K_BYPASS_EVT[]= {0x02, 0x0A, 0x01, 0x00, 0x00}; +#endif + +#if 0 +//to enable dump feature +static UINT8 WMT_CORE_DUMP_EN_CMD[] = {0x01, 0x0F, 0x02, 0x00, 0x03, 0x01}; +static UINT8 WMT_CORE_DUMP_EN_EVT[] = {0x02, 0x0F, 0x01, 0x00, 0x00}; +//to get system stack dump when f/w assert +static UCHAR WMT_CORE_DUMP_LEVEL_01_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UCHAR WMT_CORE_DUMP_LEVEL_01_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00}; +//to get task and system stack dump when f/w assert +static UCHAR WMT_CORE_DUMP_LEVEL_02_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UCHAR WMT_CORE_DUMP_LEVEL_02_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00}; +//to get bt related memory dump when f/w assert +static UCHAR WMT_CORE_DUMP_LEVEL_03_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A}; +static UCHAR WMT_CORE_DUMP_LEVEL_03_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00}; +#endif +//to get full dump when f/w assert +static UCHAR WMT_CORE_DUMP_LEVEL_04_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UCHAR WMT_CORE_DUMP_LEVEL_04_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00}; + +static UCHAR WMT_CORE_CO_CLOCK_CMD[] = {0x1, 0x0A, 0x02, 0x00, 0x08, 0x03}; +static UCHAR WMT_CORE_CO_CLOCK_EVT[] = {0x2, 0x0A, 0x01, 0x00, 0x00}; + + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static UCHAR WMT_SET_I2S_SLAVE_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0x78, 0x00, 0x05, 0x80/*addr:0x80050078*/ + ,0x00, 0x00, 0x11, 0x01/*value:0x11010000*/ + ,0x00, 0x00, 0x77, 0x07/*mask:0x07770000*/ +}; +static UCHAR WMT_SET_I2S_SLAVE_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; + +static UCHAR WMT_SET_DAI_TO_PAD_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0x74, 0x00, 0x05, 0x80/*addr:0x80050074*/ + ,0x44, 0x44, 0x00, 0x00/*value:0x11010000*/ + ,0x77, 0x77, 0x00, 0x00/*mask:0x07770000*/ +}; + +static UCHAR WMT_SET_DAI_TO_PAD_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; +static UCHAR WMT_SET_DAI_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0xA0, 0x00, 0x05, 0x80/*addr:0x80050074*/ + ,0x04, 0x00, 0x00, 0x00/*value:0x11010000*/ + ,0x04, 0x00, 0x00, 0x00/*mask:0x07770000*/ +}; +static UCHAR WMT_SET_DAI_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; +#endif + + +#ifndef CFG_IC_MT6628 //For MT6628 no need to set ALLEINT registers, done in f/w +/* enable all interrupt */ +static UCHAR WMT_SET_ALLINT_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0x00, 0x03, 0x05, 0x80/*addr:0x80050300*/ + ,0x00, 0xC4, 0x00, 0x00/*value:0x0000C400*/ + ,0x00, 0xC4, 0x00, 0x00/*mask:0x0000C400*/ +}; + +static UCHAR WMT_SET_ALLINT_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; + +#endif + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UCHAR WMT_SET_SWLA_REG_CMD[] = {0x01, 0x08, 0x1C, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ + ,0x10, 0x01, 0x05, 0x80/*addr:0x80050110*/ + ,0x10, 0x10, 0x01, 0x00/*value:0x00011010*/ + ,0xF0, 0xF0, 0x0F, 0x00/*mask:0x000FF0F0*/ + ,0x40, 0x01, 0x05, 0x80/*addr:0x80050140*/ + ,0x00, 0x10, 0x01, 0x00/*value:0x00011000*/ + ,0x00, 0xF0, 0x0F, 0x00/*mask:0x000FF000*/ +}; +static UCHAR WMT_SET_SWLA_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UCHAR WMT_SET_MCUCLK_REG_CMD[] = {0x01, 0x08, (4 + 12*4), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + ,0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + ,0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + ,0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + ,0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + ,0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + ,0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UCHAR WMT_SET_MCUCLK_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UCHAR WMT_SET_DBGUART_REG_CMD[] = {0x01, 0x08, 0x1C, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ + ,0x30, 0x01, 0x05, 0x80/*addr:0x80050130*/ + ,0x00, 0x00, 0x00, 0x00/*value:0x00000000*/ + ,0xF0, 0x0F, 0x00, 0x00/*mask:0x00000FF0*/ + ,0x40, 0x01, 0x05, 0x80/*addr:0x80050140*/ + ,0x00, 0x01, 0x00, 0x00/*value:0x00000100*/ + ,0x00, 0x01, 0x00, 0x00/*mask:0x00000100*/ +}; +static UCHAR WMT_SET_DBGUART_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x02 /*2 registers*/ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UCHAR WMT_SET_MCUIRQ_REG_CMD[] = {0x01, 0x08, (4 + 12*4), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 4 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + ,0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + ,0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + ,0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + ,0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + ,0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + ,0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + ,0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + ,0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UCHAR WMT_SET_MCUIRQ_REG_CMD[] = {0x01, 0x08, (4 + 12*5), 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /* type: reg */ + ,0x00 /* rev */ + ,0x05 /* 5 registers */ + ,0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + ,0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + ,0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + ,0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + ,0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + ,0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + ,0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + ,0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + ,0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + ,0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + ,0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + ,0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + ,0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + ,0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + ,0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /* S: 0 */ + ,0x00 /* type: reg */ + ,0x00 /* rev */ + ,0x05 /* 5 registers */ +}; +#endif +#endif + +static UCHAR WMT_SET_CRYSTAL_TRIMING_CMD[] = {0x01, 0x12, 0x02, 0x00, 0x01, 0x00}; +static UCHAR WMT_SET_CRYSTAL_TRIMING_EVT[] = {0x02, 0x12, 0x02, 0x00, 0x01, 0x00}; + +static UCHAR WMT_GET_CRYSTAL_TRIMING_CMD[] = {0x01, 0x12, 0x02, 0x00, 0x00, 0x00}; +static UCHAR WMT_GET_CRYSTAL_TRIMING_EVT[] = {0x02, 0x12, 0x02, 0x00, 0x00, 0x00}; + +/* set sdio driving */ +static UCHAR WMT_SET_SDIO_DRV_REG_CMD[] = {0x01, 0x08, 0x10, 0x00/*length*/ + ,0x01 /* op: w */ + ,0x01 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ + ,0x50, 0x00, 0x05, 0x80/*addr:0x80050050*/ + ,0x44, 0x44, 0x04, 0x00/*value:0x00044444*/ + ,0x77, 0x77, 0x07, 0x00/*mask:0x00077777*/ +}; + +static UCHAR WMT_SET_SDIO_DRV_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/ + ,0x00 /*S: 0*/ + ,0x00 /*type: reg */ + ,0x00 /*rev*/ + ,0x01 /*1 registers*/ +}; + + +#ifndef CFG_IC_MT6628 + +/* stp sdio init scripts */ +static struct init_script init_table_1_1[] = +{ + /* table_1_1 is only applied to common SDIO interface */ + INIT_CMD(WMT_SET_ALLINT_REG_CMD, WMT_SET_ALLINT_REG_EVT, "enable all interrupt"), + /* applied to MT6628 ? */ + INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"), +}; + +#endif + +static struct init_script init_table_1_2[] = +{ + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_115200, "query baud 115200"), + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"), + INIT_CMD(WMT_SET_BAUD_CMD_X, WMT_SET_BAUD_EVT, "set baud rate"), +}; + + +static struct init_script init_table_2[] = +{ + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; + +static struct init_script init_table_3[] = +{ + INIT_CMD(WMT_RESET_CMD, WMT_RESET_EVT, "wmt reset"), +#if CFG_WMT_BT_PORT2 + INIT_CMD(WMT_BTP2_CMD, WMT_BTP2_EVT, "set bt port2"), +#endif +}; + +static struct init_script set_crystal_timing_script[] = +{ + INIT_CMD(WMT_SET_CRYSTAL_TRIMING_CMD, WMT_SET_CRYSTAL_TRIMING_EVT, "set crystal trim value"), +}; + +static struct init_script get_crystal_timing_script[] = +{ + INIT_CMD(WMT_GET_CRYSTAL_TRIMING_CMD, WMT_GET_CRYSTAL_TRIMING_EVT, "get crystal trim value"), +}; + + +#if 0 +static struct init_script init_table_3_1[] = +{ + INIT_CMD(WMT_WAKEUP_EN_GATE_CMD, WMT_WAKEUP_EN_GATE_EVT, "ensable gating"), +}; +#endif + +static struct init_script init_table_4[] = +{ + INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), +}; + +static struct init_script init_table_5[] = +{ + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_UART, "query stp uart"), + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; + +static struct init_script init_table_5_1[] = { + INIT_CMD(WMT_STRAP_CONF_CMD_FM_COMM, WMT_STRAP_CONF_EVT, "configure FM comm"), +}; + +static struct init_script init_table_6[] = { +#if 0 + INIT_CMD(WMT_CORE_DUMP_EN_CMD, WMT_CORE_DUMP_EN_EVT, "configure memory and core dump"), +#endif + INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD, WMT_CORE_DUMP_LEVEL_04_EVT , "setup core dump level"), +}; + +#if 0 +static struct init_script init_table_6[] = +{ + INIT_CMD(WMT_SET_OSC32K_BYPASS_CMD, WMT_SET_OSC32K_BYPASS_EVT, "set OSC32k by pass mode."), +}; +#endif + +#if defined(CFG_SET_OPT_REG) && CFG_SET_OPT_REG +static struct init_script set_registers[] = +{ + //INIT_CMD(WMT_SET_GPS_REG_CMD, WMT_SET_GPS_REG_EVT, "set wmt registers"), + //INIT_CMD(WMT_SET_SDIODRV_REG_CMD, WMT_SET_SDIODRV_REG_EVT, "set SDIO driving registers") + #if CFG_WMT_I2S_DBGUART_SUPPORT + INIT_CMD(WMT_SET_DBGUART_REG_CMD, WMT_SET_DBGUART_REG_EVT, "set debug uart registers"), + #endif + #if CFG_SET_OPT_REG_SWLA + INIT_CMD(WMT_SET_SWLA_REG_CMD, WMT_SET_SWLA_REG_EVT, "set swla registers"), + #endif + #if CFG_SET_OPT_REG_MCUCLK + INIT_CMD(WMT_SET_MCUCLK_REG_CMD, WMT_SET_MCUCLK_REG_EVT, "set mcuclk dbg registers"), + #endif + #if CFG_SET_OPT_REG_MCUIRQ + INIT_CMD(WMT_SET_MCUIRQ_REG_CMD, WMT_SET_MCUIRQ_REG_EVT, "set mcu irq dbg registers"), + #endif +}; +#endif + +static struct init_script coex_table[] = { + INIT_CMD(WMT_COEX_SETTING_CONFIG_CMD, WMT_COEX_SETTING_CONFIG_EVT, "coex_wmt"), + +#if CFG_SUBSYS_COEX_NEED +//no need in MT6628 + INIT_CMD(WMT_BT_COEX_SETTING_CONFIG_CMD, WMT_BT_COEX_SETTING_CONFIG_EVT, "coex_bt"), + INIT_CMD(WMT_WIFI_COEX_SETTING_CONFIG_CMD, WMT_WIFI_COEX_SETTING_CONFIG_EVT, "coex_wifi"), + INIT_CMD(WMT_PTA_COEX_SETTING_CONFIG_CMD, WMT_PTA_COEX_SETTING_CONFIG_EVT, "coex_ext_pta"), + INIT_CMD(WMT_MISC_COEX_SETTING_CONFIG_CMD, WMT_MISC_COEX_SETTING_CONFIG_EVT, "coex_misc"), +#endif +}; +static struct init_script osc_type_table[] = { + INIT_CMD(WMT_CORE_CO_CLOCK_CMD, WMT_CORE_CO_CLOCK_EVT, "osc_type"), +}; + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static struct init_script merge_pcm_table[] = +{ + INIT_CMD(WMT_SET_I2S_SLAVE_REG_CMD, WMT_SET_I2S_SLAVE_REG_EVT, "I2S_Slave"), + INIT_CMD(WMT_SET_DAI_TO_PAD_REG_CMD, WMT_SET_DAI_TO_PAD_REG_EVT, "DAI_PAD"), + INIT_CMD(WMT_SET_DAI_REG_CMD, WMT_SET_DAI_REG_EVT, "DAI_EVT"), +}; +#endif + + +static struct init_script sdio_driving_table[] = { + INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), +}; + + +/* MT6628 Chip Version and Info Table */ +static const WMT_IC_INFO_S mt6628_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_MT6628, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + //need to refine? + .eWmtHwVer = WMTHWVER_MT6620_E1, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A10, + .cChipName = WMT_IC_NAME_MT6628, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E2, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B10, + .cChipName = WMT_IC_NAME_MT6628, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E3, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B11, + .cChipName = WMT_IC_NAME_MT6628, + .cChipVersion = WMT_IC_VER_E4, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E4, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8a11, + .cChipName = WMT_IC_NAME_MT6628, + .cChipVersion = WMT_IC_VER_E5, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .eWmtHwVer = WMTHWVER_MT6620_E5, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + } +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 +mt6628_sw_init ( + P_WMT_HIF_CONF pWmtHifConf + ); + +static INT32 +mt6628_sw_deinit ( + P_WMT_HIF_CONF pWmtHifConf + ); + +static INT32 +mt6628_pin_ctrl ( + WMT_IC_PIN_ID id, + WMT_IC_PIN_STATE state, + UINT32 flag + ); + +static INT32 +mt6628_aif_ctrl ( + WMT_IC_PIN_STATE state, + UINT32 flag + ); + +static INT32 +mt6628_ver_check (VOID); + +static const WMT_IC_INFO_S* +mt6628_find_wmt_ic_info ( + const UINT32 hw_ver + ); + +static INT32 +wmt_stp_init_coex (VOID); + +#if CFG_WMT_MULTI_PATCH +static INT32 mt6628_patch_dwn (UINT32 index); +static INT32 mt6628_patch_info_prepare(VOID); +#else +static INT32 mt6628_patch_dwn (VOID); +#endif + +static INT32 +mt6628_co_clock_ctrl(WMT_CO_CLOCK on); +static WMT_CO_CLOCK mt6628_co_clock_get(VOID); + +static INT32 +mt6628_crystal_triming_set (VOID); + + +static MTK_WCN_BOOL mt6628_quick_sleep_flag_get(VOID); + +static MTK_WCN_BOOL mt6628_aee_dump_flag_get(VOID); + +static INT32 mt6628_set_sdio_driving(void); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* MT6628 Operation Function Table */ +const WMT_IC_OPS wmt_ic_ops_mt6628 = { + .icId = 0x6628, + .sw_init = mt6628_sw_init, + .sw_deinit = mt6628_sw_deinit, + .ic_pin_ctrl = mt6628_pin_ctrl, + .ic_ver_check = mt6628_ver_check, + .co_clock_ctrl = mt6628_co_clock_ctrl, + .is_quick_sleep = mt6628_quick_sleep_flag_get, + .is_aee_dump_support = mt6628_aee_dump_flag_get, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static INT32 +mt6628_sw_init ( + P_WMT_HIF_CONF pWmtHifConf + ) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + UCHAR evtBuf[256]; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + UINT32 hw_ver; +#if CFG_WMT_MULTI_PATCH + UINT32 patch_num = 0; + UINT32 patch_index = 0; +#endif + WMT_DBG_FUNC(" start\n"); + + osal_assert(NULL != gp_mt6628_info); + if ( (NULL == gp_mt6628_info) + || (NULL == pWmtHifConf) + ) { + WMT_ERR_FUNC("null pointers: gp_mt6628_info(0x%p), pWmtHifConf(0x%p)\n", + gp_mt6628_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_mt6628_info->u4HwVer; + + //4 <3.1> start init for sdio +#ifndef CFG_IC_MT6628 //For MT6628 no need to do this operation + if (WMT_HIF_SDIO == pWmtHifConf->hifType) { + wmt_lib_ps_set_idle_time(STP_PSM_SDIO_IDLE_TIME_SLEEP); + /* 1. enable all INT32 */ + /* 2. disable mcu gate (only MT6628E1/E2) */ + iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet); + osal_assert(0); + return -1; + } + } +#endif + //4 <3.2> start init for uart + if (WMT_HIF_UART == pWmtHifConf->hifType) { + /* init variable fields for script execution */ + osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//0xC0 MTK Flow Control /* no flow control */ + osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32)); + WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //0xC0 MTK Flow Control /* no flow control */ + + /* 3. Query chip baud rate (TEST-ONLY) */ + /* 4. Query chip STP options (TEST-ONLY) */ + /* 5. Change chip baud rate: t_baud */ + //WMT_DBG_FUNC("WMT-CORE: init_table_1_2 set chip baud:%d", pWmtHifConf->au4HifConf[0]); + iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); + osal_assert(0); + return -2; + } + + /* 6. Set host baudrate and flow control*/ + ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet); + return -3; + } + WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]); + + /* 7. Wake up chip and check event */ +// iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res); + iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != 1)) { + WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res); + return -4; + } + + osal_memset(evtBuf, 0, osal_sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res); +#ifdef CFG_DUMP_EVT + WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n", + (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); +#endif + if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) { + WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet); + return -5; + } + //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok"); + +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n"); + return -6; + } +#endif + + /* 8. Query baud rate (TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet); + return -7; + } + } + + /* 9. download patch */ +#if CFG_WMT_MULTI_PATCH + /* 9.1 Let launcher to search patch info */ + iRet = mt6628_patch_info_prepare(); + if (iRet) { + WMT_ERR_FUNC("patch info perpare fail(%d)\n", iRet); + return -8; + } + + /* 9.2 Read patch number */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM, &ctrlPa1, &ctrlPa2); + patch_num = ctrlPa1; + WMT_INFO_FUNC("patch total num = [%d]\n", patch_num); + + /* 9.3 Multi-patch Patch download */ + for (patch_index = 0; patch_index < patch_num; patch_index++) { + iRet = mt6628_patch_dwn(patch_index); + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index); + return -12; + } + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -13; + } + } +#else + /* 9.3 Patch download */ + iRet = mt6628_patch_dwn(); + //If patch download fail, we just ignore this error and let chip init process goes on + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d), just omit\n", iRet); + } +#endif // End of #if CFG_WMT_MULTI_PATCH + + /* 10. WMT Reset command */ + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -9; + } + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + else { + WMT_INFO_FUNC("init_coex ok\n"); + } + + mt6628_crystal_triming_set(); + + mt6628_set_sdio_driving(); + + if (WMT_HIF_UART == pWmtHifConf->hifType) { + /* 11. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); + if (iRet) { + WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); + return -12; + } + + /* 12. Enable host STP-UART mode */ + ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_FULL_MODE; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("enable host STP-UART-FULL mode fail(%d)\n", iRet); + return -13; + } + WMT_INFO_FUNC("enable host STP-UART-FULL mode\n"); + /*13. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/ + osal_msleep(10); + /* 14. Query chip STP options (TEST-ONLY) */ + /* 15. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -14; + } + } + + if (WMT_CO_CLOCK_EN == mt6628_co_clock_get()) + { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, osal_array_size(osc_type_table)); + if (iRet) { + WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); + return -15; + } + } + else + { + WMT_INFO_FUNC("co-clock disabled.\n"); + } + #if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + iRet = wmt_core_init_script(merge_pcm_table, osal_array_size(merge_pcm_table)); + if (iRet) { + WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); + return -15; + } + #endif + + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UCHAR)pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", + pWmtHifConf->au4StrapConf[0], + iRet); + return -16; + } + WMT_INFO_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); + +#if CFG_SET_OPT_REG /*set registers*/ + iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); + if (iRet) { + WMT_ERR_FUNC("set_registers fail(%d)", iRet); + return -17; + } +#endif + +#if CFG_WMT_COREDUMP_ENABLE + /*Open Core Dump Function @QC begin*/ + mtk_wcn_stp_coredump_flag_ctrl(1); +#endif + if (0 != mtk_wcn_stp_coredump_flag_get()) + { + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", + iRet); + return -18; + } else { + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } + } + else + { + WMT_INFO_FUNC("disable mt662x firmware coredump\n"); + } + + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_mt6628_info); + if (NULL != gp_mt6628_info) { + if (MTK_WCN_BOOL_FALSE != gp_mt6628_info->bPsmSupport) { + wmt_lib_ps_enable(); + } + else { + wmt_lib_ps_disable(); + } + } +#endif + + return 0; +} + +static INT32 +mt6628_sw_deinit ( + P_WMT_HIF_CONF pWmtHifConf + ) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_mt6628_info); + if ( (NULL != gp_mt6628_info) + && (MTK_WCN_BOOL_FALSE != gp_mt6628_info->bPsmSupport) ) { + wmt_lib_ps_disable(); + } +#endif + + gp_mt6628_info = NULL; + + return 0; +} + +static INT32 +mt6628_aif_ctrl ( + WMT_IC_PIN_STATE state, + UINT32 flag + ) +{ + INT32 ret = -1; + UINT32 val; + + if ( (flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE ) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); + #if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000710; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + default: + WMT_ERR_FUNC("unsupported state (%d) \n", state); + ret = -1; + break; + } + #else + WMT_WARN_FUNC("TBD!!"); + ret = 0; + #endif + } + else { + /*PCM & I2S separate*/ + WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n"); + #if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000070; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + case WMT_IC_AIF_3: + val = 0x00000000; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + default: + WMT_ERR_FUNC("unsupported state (%d) \n", state); + ret = -1; + break; + } + #else + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + ret = 0; + break; + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + ret = 0; + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); + + break; + case WMT_IC_AIF_3: + ret = 0; + break; + + default: + WMT_ERR_FUNC("unsupported state (%d) \n", state); + ret = -1; + break; + } + #endif + } + + if (!ret) { + WMT_INFO_FUNC("new state(%d) ok\n", state); + } + else { + WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret); + } + + return ret; +} + +static INT32 +mt6628_gps_sync_ctrl ( + WMT_IC_PIN_STATE state, + UINT32 flag + ) +{ + INT32 iRet = -1; + UINT32 uVal = 0; + if (WMT_IC_PIN_MUX == state) + { + uVal = 0x1 << 28; + } + else + { + uVal = 0x5 << 28; + } + iRet = wmt_core_reg_rw_raw(1, 0x80050078, &uVal, 0x7 << 28); + if (0 != iRet) + { + WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet); + } + // anyway, we return 0 + return 0; +} + + +static INT32 +mt6628_pin_ctrl ( + WMT_IC_PIN_ID id, + WMT_IC_PIN_STATE state, + UINT32 flag + ) +{ + INT32 ret; + + WMT_DBG_FUNC("ic pin id:%d, state:%d, flag:0x%x\n", id , state, flag); + + ret = -1; + switch (id) { + case WMT_IC_PIN_AUDIO: + ret = mt6628_aif_ctrl(state, flag); + break; + + case WMT_IC_PIN_EEDI: + WMT_WARN_FUNC("TBD!!"); + //We just return 0 here, prevent from WMT-FUNC do other register read/write + ret = 0; + break; + + case WMT_IC_PIN_EEDO: + WMT_WARN_FUNC("TBD!!"); + //We just return 0 here, prevent from WMT-FUNC do other register read/write + ret = 0; + break; + case WMT_IC_PIN_GSYNC: + ret = mt6628_gps_sync_ctrl(state, flag); + break; + default: + break; + } + WMT_INFO_FUNC("ret = (%d)\n" , ret); + + return ret; +} + +INT32 mt6628_co_clock_ctrl(WMT_CO_CLOCK on) +{ + INT32 iRet = 0; + if ((WMT_CO_CLOCK_DIS <= on) && (WMT_CO_CLOCK_MAX > on)) + { + gCoClockEn = on; + } + else + { + WMT_DBG_FUNC("MT6628: error parameter:%d\n", on); + iRet = -1; + } + WMT_DBG_FUNC("MT6628: Co-clock %s\n", (gCoClockEn == WMT_CO_CLOCK_DIS) ? "disabled" : "enabled"); + + return iRet; +} + +static MTK_WCN_BOOL mt6628_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + + +static MTK_WCN_BOOL mt6628_aee_dump_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + + +WMT_CO_CLOCK mt6628_co_clock_get(VOID) +{ + return gCoClockEn; +} + + + +static INT32 +mt6628_ver_check (VOID) +{ + UINT32 hw_ver; + UINT32 fw_ver; + INT32 iret; + const WMT_IC_INFO_S *p_info; + UINT32 ctrlPa1; + UINT32 ctrlPa2; + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("MT6628: before read hw_ver (hw version)\n"); + iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("MT6628: read hw_ver fail:%d\n", iret); + return -2; + } + WMT_INFO_FUNC("MT6628: read hw_ver (hw version) (0x%x)\n", hw_ver); + + WMT_LOUD_FUNC("MT6628: before fw_ver (rom version) \n"); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("MT6628: read fw_ver fail:%d\n", iret); + return -2; + } + WMT_INFO_FUNC("MT6628: read fw_ver (rom version) (0x%x)\n", fw_ver); + + p_info = mt6628_find_wmt_ic_info(hw_ver); + if (NULL == p_info) { + WMT_ERR_FUNC("MT6628: hw_ver(0x%x) find wmt ic info fail\n"); + return -3; + } + + WMT_INFO_FUNC("MT6628: wmt ic info: %s.%s (0x%x, WMTHWVER:%d, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->eWmtHwVer, + p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006628UL << 16) | (hw_ver & 0x0000FFFF); + /* translated hw version & fw rom version */ + ctrlPa2 = ((UINT32)(p_info->eWmtHwVer) << 16) | (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + if (iret) { + WMT_WARN_FUNC("MT6628: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret); + } + + gp_mt6628_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S* +mt6628_find_wmt_ic_info ( + const UINT32 hw_ver + ) +{ + /* match chipversion with u4HwVer item in mt6628_info_table */ + const UINT32 size = osal_array_size(mt6628_info_table); + INT32 index; + + /* George: reverse the search order to favor newer version products */ + // TODO:[FixMe][GeorgeKuo] Remove full match once API wmt_lib_get_hwver() is changed correctly in the future!! + // Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. + index = size - 1; + /* full match */ + while ( (0 <= index) + && (hw_ver != mt6628_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + if (0 <= index) { + WMT_INFO_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mt6628_info_table[index]; + } + + WMT_WARN_FUNC("find no ic info for (0x%x) by full match!try major num match!\n", hw_ver); + + /* George: The ONLY CORRECT method to find supported hw table. Match MAJOR + * NUM only can help us support future minor hw ECO, or fab switch, etc. + * FULL matching eliminate such flexibility and software package have to be + * updated EACH TIME even when minor hw ECO or fab switch!!! + */ + /* George: reverse the search order to favor newer version products */ + index = size - 1; + /* major num match */ + while ( (0 <= index) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6628_info_table[index].u4HwVer)) + ) { + --index; + } + if (0 <= index) { + WMT_INFO_FUNC("MT6628: found ic info for hw_ver(0x%x) by major num! index:%d\n", hw_ver, index); + return &mt6628_info_table[index]; + } + + WMT_ERR_FUNC("MT6628: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", hw_ver); + return NULL; +} + + +static INT32 +wmt_stp_init_coex (VOID) +{ + INT32 iRet; + UINT32 addr; + WMT_GEN_CONF *pWmtGenConf; + + #define COEX_WMT 0 + +#if CFG_SUBSYS_COEX_NEED + //no need for MT6628 + #define COEX_BT 1 + #define COEX_WIFI 2 + #define COEX_PTA 3 + #define COEX_MISC 4 +#endif + /*Get wmt config*/ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF)addr; + + /*Check if WMT.cfg exists*/ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value*/ + return 0; + } + + + /*Dump the coex-related info*/ + WMT_DBG_FUNC("coex_wmt:0x%x\n", + pWmtGenConf->coex_wmt_ant_mode + ); +#if CFG_SUBSYS_COEX_NEED + WMT_DBG_FUNC("coex_bt:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_bt_rssi_upper_limit, + pWmtGenConf->coex_bt_rssi_mid_limit, + pWmtGenConf->coex_bt_rssi_lower_limit, + pWmtGenConf->coex_bt_pwr_high, + pWmtGenConf->coex_bt_pwr_mid, + pWmtGenConf->coex_bt_pwr_low + ); + WMT_DBG_FUNC("coex_wifi:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_wifi_rssi_upper_limit, + pWmtGenConf->coex_wifi_rssi_mid_limit, + pWmtGenConf->coex_wifi_rssi_lower_limit, + pWmtGenConf->coex_wifi_pwr_high, + pWmtGenConf->coex_wifi_pwr_mid, + pWmtGenConf->coex_wifi_pwr_low + ); + WMT_DBG_FUNC("coex_ext_pta:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_ext_pta_hi_tx_tag, + pWmtGenConf->coex_ext_pta_hi_rx_tag, + pWmtGenConf->coex_ext_pta_lo_tx_tag, + pWmtGenConf->coex_ext_pta_lo_rx_tag, + pWmtGenConf->coex_ext_pta_sample_t1, + pWmtGenConf->coex_ext_pta_sample_t2, + pWmtGenConf->coex_ext_pta_wifi_bt_con_trx + ); + WMT_DBG_FUNC("coex_misc:0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_misc_ext_pta_on, + pWmtGenConf->coex_misc_ext_feature_set + ); +#endif + + /*command adjustion due to WMT.cfg*/ + coex_table[COEX_WMT].cmd[5]= pWmtGenConf->coex_wmt_ant_mode; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WMT].cmd[0], + coex_table[COEX_WMT].str, + coex_table[COEX_WMT].cmdSz); + } + +#if CFG_SUBSYS_COEX_NEED + coex_table[COEX_BT].cmd[9]= pWmtGenConf->coex_bt_rssi_upper_limit; + coex_table[COEX_BT].cmd[10]= pWmtGenConf->coex_bt_rssi_mid_limit; + coex_table[COEX_BT].cmd[11]= pWmtGenConf->coex_bt_rssi_lower_limit; + coex_table[COEX_BT].cmd[12]= pWmtGenConf->coex_bt_pwr_high; + coex_table[COEX_BT].cmd[13]= pWmtGenConf->coex_bt_pwr_mid; + coex_table[COEX_BT].cmd[14]= pWmtGenConf->coex_bt_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_BT].cmd[0], + coex_table[COEX_BT].str, + coex_table[COEX_BT].cmdSz); + } + coex_table[COEX_WIFI].cmd[10]= pWmtGenConf->coex_wifi_rssi_upper_limit; + coex_table[COEX_WIFI].cmd[11]= pWmtGenConf->coex_wifi_rssi_mid_limit; + coex_table[COEX_WIFI].cmd[12]= pWmtGenConf->coex_wifi_rssi_lower_limit; + coex_table[COEX_WIFI].cmd[13]= pWmtGenConf->coex_wifi_pwr_high; + coex_table[COEX_WIFI].cmd[14]= pWmtGenConf->coex_wifi_pwr_mid; + coex_table[COEX_WIFI].cmd[15]= pWmtGenConf->coex_wifi_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WIFI].cmd[0], + coex_table[COEX_WIFI].str, + coex_table[COEX_WIFI].cmdSz); + } + coex_table[COEX_PTA].cmd[5]= pWmtGenConf->coex_ext_pta_hi_tx_tag; + coex_table[COEX_PTA].cmd[6]= pWmtGenConf->coex_ext_pta_hi_rx_tag; + coex_table[COEX_PTA].cmd[7]= pWmtGenConf->coex_ext_pta_lo_tx_tag; + coex_table[COEX_PTA].cmd[8]= pWmtGenConf->coex_ext_pta_lo_rx_tag; + coex_table[COEX_PTA].cmd[9]= ((pWmtGenConf->coex_ext_pta_sample_t1 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[10]= ((pWmtGenConf->coex_ext_pta_sample_t1 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[11]= ((pWmtGenConf->coex_ext_pta_sample_t2 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[12]= ((pWmtGenConf->coex_ext_pta_sample_t2 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[13]= pWmtGenConf->coex_ext_pta_wifi_bt_con_trx; + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_PTA].cmd[0], + coex_table[COEX_PTA].str, + coex_table[COEX_PTA].cmdSz); + } + + osal_memcpy(&coex_table[COEX_MISC].cmd[5], &pWmtGenConf->coex_misc_ext_pta_on, sizeof(pWmtGenConf->coex_misc_ext_pta_on)); + osal_memcpy(&coex_table[COEX_MISC].cmd[9], &pWmtGenConf->coex_misc_ext_feature_set, sizeof(pWmtGenConf->coex_misc_ext_feature_set)); + + wmt_core_dump_data(& coex_table[COEX_MISC].cmd[0], coex_table[COEX_MISC].str, coex_table[COEX_MISC].cmdSz); +#endif + + iRet = wmt_core_init_script(coex_table, sizeof(coex_table)/sizeof(coex_table[0])); + + return iRet; +} + + +static INT32 mt6628_set_sdio_driving(void) +{ + INT32 ret = 0; + + UINT32 addr; + WMT_GEN_CONF *pWmtGenConf; + UINT32 drv_val = 0; + + /*Get wmt config*/ + ret = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (ret) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", ret); + return -1; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF)addr; + + /*Check if WMT.cfg exists*/ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value*/ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info*/ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12]= (UCHAR)((drv_val & 0x00000077UL) >> 0); // DAT0 and DAT1 + sdio_driving_table[0].cmd[13]= (UCHAR)((drv_val & 0x00007700UL) >> 8); // DAT2 and DAT3 + sdio_driving_table[0].cmd[14]= (UCHAR)((drv_val & 0x00070000UL) >> 16); // CMD + + ret = wmt_core_init_script(sdio_driving_table, sizeof(sdio_driving_table)/sizeof(sdio_driving_table[0])); + + return ret; +} + + +static INT32 +mt6628_crystal_triming_set (VOID) +{ + INT32 iRet = 0; + PUINT8 pbuf = NULL; + UINT32 bufLen = 0; + WMT_CTRL_DATA ctrlData; + UINT32 uCryTimOffset = 0x6D; + MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; + CHAR cCrystalTimingOffset = 0x0; + UCHAR cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + bIsNvramExist = MTK_WCN_BOOL_FALSE; + /**/ + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (UINT32)"/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (UINT32)&pbuf; + ctrlData.au4CtrlData[2] = (UINT32)&bufLen; + + iRet = wmt_ctrl(&ctrlData); + if (0 != iRet) { + WMT_ERR_FUNC("MT6628: WMT_CTRL_CRYSTAL_TRIMING_GET fail:%d \n", iRet); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + iRet = -1; + } + else + { + WMT_DBG_FUNC("MT6628: nvram pBuf(0x%08x), bufLen(%d)\n", pbuf, bufLen); + if (bufLen < (uCryTimOffset + 1)) + { + WMT_ERR_FUNC("MT6628: nvram len(%d) too short, crystalTimging value offset(%d)\n", bufLen, uCryTimOffset); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + } + else + { + bIsNvramExist = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = *(pbuf + uCryTimOffset); + if(cCrystalTimingOffset & 0x80) + { + bIsCrysTrimEnabled = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = (UCHAR)cCrystalTimingOffset & 0x7f; + } + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", cCrystalTimingOffset, bIsCrysTrimEnabled); + } + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (UINT32)"/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + if (0 != iRet) { + WMT_ERR_FUNC("MT6628: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d \n", iRet); + iRet = -2; + } + else + { + WMT_DBG_FUNC("MT6628: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n"); + } + } + if ((MTK_WCN_BOOL_TRUE == bIsNvramExist) && (MTK_WCN_BOOL_TRUE == bIsCrysTrimEnabled)) + { + /*get CrystalTiming value before set it*/ + iRet = wmt_core_tx(get_crystal_timing_script[0].cmd, get_crystal_timing_script[0].cmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != get_crystal_timing_script[0].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d) \n", get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].cmdSz); + iRet = -3; + goto done; + } + /* EVENT BUF */ + osal_memset(get_crystal_timing_script[0].evt, 0, get_crystal_timing_script[0].evtSz); + iRet = wmt_core_rx(get_crystal_timing_script[0].evt, get_crystal_timing_script[0].evtSz, &u4Res); + if (iRet || (u4Res != get_crystal_timing_script[0].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d) \n", get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].evtSz); + mtk_wcn_stp_dbg_dump_package(); + iRet = -4; + goto done; + } + + iCrystalTiming = WMT_GET_CRYSTAL_TRIMING_EVT[5] & 0x7f; + if (cCrystalTimingOffset & 0x40) + { + /*nagative offset value*/ + iCrystalTiming = iCrystalTiming + cCrystalTimingOffset - 128; + } + else + { + iCrystalTiming += cCrystalTimingOffset; + } + WMT_DBG_FUNC("iCrystalTiming (0x%x)\n", iCrystalTiming); + cCrystalTiming = iCrystalTiming > 0x7f ? 0x7f : iCrystalTiming; + cCrystalTiming = iCrystalTiming < 0 ? 0 : iCrystalTiming; + WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); + //set_crystal_timing_script + WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; + WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; + + iRet = wmt_core_init_script(set_crystal_timing_script, osal_array_size(set_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("set_crystal_timing_script fail(%d)\n", iRet); + iRet = -5; + } + else + { + WMT_DBG_FUNC("set crystal timing value (0x%x) succeed\n", WMT_SET_CRYSTAL_TRIMING_CMD[5]); + iRet = wmt_core_init_script(get_crystal_timing_script, osal_array_size(get_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); + iRet = -6; + } + else + { + WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", WMT_GET_CRYSTAL_TRIMING_EVT[5]); + iRet = 0x0; + } + } + } +done: + return iRet; +} + + +#if CFG_WMT_MULTI_PATCH +static INT32 mt6628_patch_info_prepare(VOID) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + + return iRet; +} + + +static INT32 +mt6628_patch_dwn (UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + UINT8 addressevtBuf[12]; + UCHAR addressByte[4]; + PCHAR cDataTime = NULL; + /*PCHAR cPlat = NULL;*/ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_mt6628_info) { + WMT_ERR_FUNC("null gp_mt6628_info!\n"); + return -1; + } + + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + ctrlData.au4CtrlData[2] = (UINT32)&addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_INFO_FUNC("the %d time valid patch found: (%s)\n", index+1, gFullPatchName); + + //<2.2> read patch content + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32)NULL; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + ctrlData.au4CtrlData[2] = (UINT32)&pbuf; + ctrlData.au4CtrlData[3] = (UINT32)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d \n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH)pbuf; + // check patch file information + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0];*/ + + cDataTime[15] = '\0'; + if (index == 0) { + WMT_INFO_FUNC("===========================================\n"); + WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime); + WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n", ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], + patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_INFO_FUNC("===========================================\n"); + } + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /*send wmt part patch address command*/ + iRet = wmt_core_tx((PUINT8)&WMT_PATCH_ADDRESS_CMD[0], sizeof(WMT_PATCH_ADDRESS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt patch address CMD fail(%d),size(%d)\n", iRet, u4Res); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf,sizeof(WMT_PATCH_ADDRESS_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d)\n", iRet, u4Res); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail\n"); + iRet -= 1; + goto done; + } +#endif + + /*send part patch address command*/ + osal_memcpy(&WMT_PATCH_P_ADDRESS_CMD[12], addressByte, osal_sizeof(addressByte)); + WMT_INFO_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", + WMT_PATCH_P_ADDRESS_CMD[12], + WMT_PATCH_P_ADDRESS_CMD[13], + WMT_PATCH_P_ADDRESS_CMD[14], + WMT_PATCH_P_ADDRESS_CMD[15]); + iRet = wmt_core_tx((PUINT8)&WMT_PATCH_P_ADDRESS_CMD[0], sizeof(WMT_PATCH_P_ADDRESS_CMD), &u4Res,MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf,sizeof(WMT_PATCH_P_ADDRESS_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_P_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail,index(%d)\n",index); + iRet -= 1; + goto done; + } +#endif + + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum-1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } + else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST: WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag*/ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + //iRet = (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res); + iRet = wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet ); + iRet -= 1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + //iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), u4Res, iRet); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT result error rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], sizeof(WMT_PATCH_EVT), WMT_PATCH_EVT[0], WMT_PATCH_EVT[1], WMT_PATCH_EVT[2], WMT_PATCH_EVT[3], WMT_PATCH_EVT[4]); + iRet -= 1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail"); + + if (fragSeq != fragNum) { + iRet -= 1; + } +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + //wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; + ctrlData.au4CtrlData[0] = index + 1; + wmt_ctrl(&ctrlData); + + return iRet; +} + +#else +static INT32 +mt6628_patch_dwn (VOID) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + PCHAR cDataTime = NULL; + /*PCHAR cPlat = NULL;*/ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_mt6628_info) { + WMT_ERR_FUNC("null gp_mt6628_info!\n"); + return -1; + } + //<2> search patch and read patch content + //<2.1> search patch + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + if (0 == iRet) + { + //patch with correct Hw Ver Major Num found + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (UINT32)&gFullPatchName; + iRet = wmt_ctrl(&ctrlData); + + WMT_INFO_FUNC("valid patch found: (%s)\n", gFullPatchName); + //<2.2> read patch content + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32)NULL; + ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName; + + } + else + { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (UINT32)&pbuf; + ctrlData.au4CtrlData[3] = (UINT32)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d \n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH)pbuf; + // check patch file information + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0];*/ + + cDataTime[15] = '\0'; + WMT_INFO_FUNC("===========================================\n"); + WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime); + WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n", ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], + patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_INFO_FUNC("===========================================\n"); + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum-1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } + else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST: WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag*/ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + //iRet = (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res); + iRet = wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet ); + iRet -= 1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + //iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), u4Res, iRet); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT result error rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], sizeof(WMT_PATCH_EVT), WMT_PATCH_EVT[0], WMT_PATCH_EVT[1], WMT_PATCH_EVT[2], WMT_PATCH_EVT[3], WMT_PATCH_EVT[4]); + iRet -= 1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail"); + + if (fragSeq != fragNum) { + iRet -= 1; + } +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + + return iRet; +} + +#endif + diff --git a/drivers/mtk_wcn_combo/common/core/wmt_lib.c b/drivers/mtk_wcn_combo/common/core/wmt_lib.c new file mode 100755 index 000000000000..17b70fea5ae3 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/core/wmt_lib.c @@ -0,0 +1,1842 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-LIB]" + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_dbg.h" + +#include "wmt_dev.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "wmt_core.h" +#include "wmt_plat.h" +#include "wmt_plat_stub.h" + +#include "stp_core.h" +#include "btm_core.h" +#include "psm_core.h" +#include "stp_sdio.h" +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* A table for translation: CMB_STUB_AIF_X=>WMT_IC_PIN_STATE */ +static const WMT_IC_PIN_STATE cmb_aif2pin_stat[] = { + [CMB_STUB_AIF_0] = WMT_IC_AIF_0, + [CMB_STUB_AIF_1] = WMT_IC_AIF_1, + [CMB_STUB_AIF_2] = WMT_IC_AIF_2, + [CMB_STUB_AIF_3] = WMT_IC_AIF_3, +}; + +#if CFG_WMT_PS_SUPPORT +static UINT32 gPsIdleTime = STP_PSM_IDLE_TIME_SLEEP; +static UINT32 gPsEnable = 1; +static PF_WMT_SDIO_PSOP sdio_own_ctrl = NULL; +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +DEV_WMT gDevWmt; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_WMT_PS_SUPPORT +static MTK_WCN_BOOL wmt_lib_ps_action (MTKSTP_PSM_ACTION_T action); +static MTK_WCN_BOOL wmt_lib_ps_do_sleep (VOID); +static MTK_WCN_BOOL wmt_lib_ps_do_wakeup (VOID); +static MTK_WCN_BOOL wmt_lib_ps_do_host_awake (VOID); +static INT32 wmt_lib_ps_handler (MTKSTP_PSM_ACTION_T action); +#endif + +static MTK_WCN_BOOL +wmt_lib_put_op ( + P_OSAL_OP_Q pOpQ, + P_OSAL_OP pLxOp + ); + +static P_OSAL_OP +wmt_lib_get_op ( + P_OSAL_OP_Q pOpQ + ); + +static INT32 +wmtd_thread ( + PVOID pvData + ); + +static INT32 +wmt_lib_pin_ctrl ( + WMT_IC_PIN_ID id, + WMT_IC_PIN_STATE stat, + UINT32 flag + ); +MTK_WCN_BOOL wmt_lib_hw_state_show(VOID); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 wmt_lib_psm_lock_aquire(void) +{ + return osal_lock_sleepable_lock(&gDevWmt.psm_lock); +} + +void wmt_lib_psm_lock_release(void) +{ + osal_unlock_sleepable_lock(&gDevWmt.psm_lock); +} + +INT32 DISABLE_PSM_MONITOR(void) +{ + INT32 ret = 0; + + //osal_lock_sleepable_lock(&gDevWmt.psm_lock); + ret = wmt_lib_psm_lock_aquire(); + if (ret) { + WMT_ERR_FUNC("--->lock psm_lock failed, ret=%d\n", ret); + return ret; + } + +#if CFG_WMT_PS_SUPPORT + ret = wmt_lib_ps_disable(); +#endif + + return ret; +} + +void ENABLE_PSM_MONITOR(void) +{ +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_enable(); +#endif + //osal_unlock_sleepable_lock(&gDevWmt.psm_lock); + wmt_lib_psm_lock_release(); +} + + +INT32 +wmt_lib_init (VOID) +{ + INT32 iRet; + UINT32 i; + P_DEV_WMT pDevWmt; + P_OSAL_THREAD pThraed; + + /* create->init->start */ + /* 1. create: static allocation with zero initialization */ + pDevWmt = &gDevWmt; + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); + +#if 0 + iRet = wmt_conf_read_file(); + if (iRet) { + WMT_ERR_FUNC("read wmt config file fail(%d)\n", iRet); + return -1; + } +#endif + + pThraed = &gDevWmt.thread; + + /* Create mtk_wmtd thread */ + osal_strncpy(pThraed->threadName, "mtk_wmtd", sizeof(pThraed->threadName)); + pThraed->pThreadData = (VOID *)pDevWmt; + pThraed->pThreadFunc = (VOID *)wmtd_thread; + iRet = osal_thread_create(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", pThraed, iRet); + return -2; + } + + /* 2. initialize */ + /* Initialize wmt_core */ + + iRet = wmt_core_init(); + if (iRet) { + WMT_ERR_FUNC("wmt_core_init() fail(%d)\n", iRet); + return -1; + } + + /* Initialize WMTd Thread Information: Thread */ + osal_event_init(&pDevWmt->rWmtdWq); + osal_sleepable_lock_init(&pDevWmt->psm_lock); + osal_sleepable_lock_init(&pDevWmt->rActiveOpQ.sLock); + osal_sleepable_lock_init(&pDevWmt->rFreeOpQ.sLock); + pDevWmt->state.data = 0; + + /* Initialize op queue */ + RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); + RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); + /* Put all to free Q */ + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_init(&(pDevWmt->arQue[i].signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); + } + + /* initialize stp resources */ + osal_event_init(&pDevWmt->rWmtRxWq); + + /*function driver callback*/ + for (i = 0 ; i < WMTDRV_TYPE_WIFI ; i++) { + pDevWmt->rFdrvCb.fDrvRst[i] = NULL; + } + pDevWmt->hw_ver = WMTHWVER_MT6620_MAX; + WMT_INFO_FUNC("***********Init, hw->ver = %x\n", pDevWmt->hw_ver); + + // TODO:[FixMe][GeorgeKuo]: wmt_lib_conf_init + /* initialize default configurations */ + //i4Result = wmt_lib_conf_init(VOID); + //WMT_WARN_FUNC("wmt_drv_conf_init(%d) \n", i4Result); + + osal_signal_init(&pDevWmt->cmdResp); + osal_event_init(&pDevWmt->cmdReq); + + /* initialize platform resources */ + if (0 != gDevWmt.rWmtGenConf.cfgExist) + { + + PWR_SEQ_TIME pwrSeqTime; + pwrSeqTime.ldoStableTime = gDevWmt.rWmtGenConf.pwr_on_ldo_slot; + pwrSeqTime.rstStableTime = gDevWmt.rWmtGenConf.pwr_on_rst_slot; + pwrSeqTime.onStableTime = gDevWmt.rWmtGenConf.pwr_on_on_slot; + pwrSeqTime.offStableTime = gDevWmt.rWmtGenConf.pwr_on_off_slot; + pwrSeqTime.rtcStableTime = gDevWmt.rWmtGenConf.pwr_on_rtc_slot; + WMT_INFO_FUNC("set pwr on seq par to hw conf\n"); + WMT_INFO_FUNC("ldo(%d)rst(%d)on(%d)off(%d)rtc(%d)\n", pwrSeqTime.ldoStableTime, pwrSeqTime.rstStableTime, pwrSeqTime.onStableTime, pwrSeqTime.offStableTime, pwrSeqTime.rtcStableTime); + iRet = wmt_plat_init(&pwrSeqTime); + } + else + { + WMT_INFO_FUNC("no pwr on seq par found\n"); + iRet = wmt_plat_init(NULL); + } + if (iRet) { + WMT_ERR_FUNC("wmt_plat_init() fail(%d)\n", iRet); + return -3; + } + wmt_plat_stub_init(); + +#if CFG_WMT_PS_SUPPORT + iRet = wmt_lib_ps_init(); + if (iRet) { + WMT_ERR_FUNC("wmt_lib_ps_init() fail(%d)\n", iRet); + return -4; + } +#endif + + /* 3. start: start running mtk_wmtd */ + iRet = osal_thread_run(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_run(0x%p) fail(%d)\n", pThraed, iRet); + return -5; + } + + /*4. register irq callback to WMT-PLAT*/ + wmt_lib_plat_irq_cb_reg(wmt_lib_ps_irq_cb); + + /*5. register audio if control callback to WMT-PLAT*/ + wmt_lib_plat_aif_cb_reg(wmt_lib_set_aif); + + + WMT_DBG_FUNC("init success\n"); + return 0; +} + + +INT32 +wmt_lib_deinit (VOID) +{ + INT32 iRet; + P_DEV_WMT pDevWmt; + P_OSAL_THREAD pThraed; + INT32 i; + INT32 iResult; + + pDevWmt = &gDevWmt; + pThraed = &gDevWmt.thread; + iResult = 0; + + /* stop->deinit->destroy */ + + /* 1. stop: stop running mtk_wmtd */ + iRet = osal_thread_stop(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); + iResult += 1; + } + + /* 2. deinit: */ + +#if CFG_WMT_PS_SUPPORT + iRet = wmt_lib_ps_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_lib_ps_deinit fail(%d)\n", iRet); + iResult += 2; + } +#endif + + iRet = wmt_plat_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_plat_deinit fail(%d)\n", iRet); + iResult += 4; + } + + osal_event_deinit(&pDevWmt->cmdReq); + osal_signal_deinit(&pDevWmt->cmdResp); + + /* de-initialize stp resources */ + osal_event_deinit(&pDevWmt->rWmtRxWq); + + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_deinit(&(pDevWmt->arQue[i].signal)); + } + + osal_sleepable_lock_deinit(&pDevWmt->rFreeOpQ.sLock); + osal_sleepable_lock_deinit(&pDevWmt->rActiveOpQ.sLock); + osal_sleepable_lock_deinit(&pDevWmt->psm_lock); + osal_event_deinit(&pDevWmt->rWmtdWq); + + iRet = wmt_core_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_core_deinit fail(%d)\n", iRet); + iResult += 8; + } + + /* 3. destroy */ + iRet = osal_thread_destroy(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); + iResult += 16; + } + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); + + return iResult; +} + +VOID +wmt_lib_flush_rx (VOID) +{ + mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); +} + +INT32 +wmt_lib_trigger_cmd_signal ( + INT32 result + ) +{ + P_OSAL_SIGNAL pSignal = &gDevWmt.cmdResp; + gDevWmt.cmdResult = result; + osal_raise_signal(pSignal); + WMT_DBG_FUNC("wakeup cmdResp\n"); + return 0; +} + +P_OSAL_EVENT +wmt_lib_get_cmd_event (VOID) +{ + return &gDevWmt.cmdReq; +} + +INT32 +wmt_lib_set_patch_name ( + UCHAR *cPatchName + ) +{ + osal_strncpy(gDevWmt.cPatchName, cPatchName, NAME_MAX); + return 0; +} +#if WMT_PLAT_ALPS +extern PCHAR wmt_uart_port_desc; // defined in mtk_wcn_cmb_stub_alps.cpp +#endif +INT32 +wmt_lib_set_uart_name( + CHAR *cUartName +) +{ +#if WMT_PLAT_ALPS + + WMT_INFO_FUNC("orig uart: %s\n", wmt_uart_port_desc); +#endif + osal_strncpy(gDevWmt.cUartName, cUartName, NAME_MAX); +#if WMT_PLAT_ALPS + wmt_uart_port_desc = gDevWmt.cUartName; + WMT_INFO_FUNC("new uart: %s\n", wmt_uart_port_desc); +#endif + return 0; +} + +INT32 +wmt_lib_set_hif ( + ULONG hifconf + ) +{ + UINT32 val; + P_WMT_HIF_CONF pHif = &gDevWmt.rWmtHifConf; + + val = hifconf & 0xF; + if (STP_UART_FULL == val) { + pHif->hifType = WMT_HIF_UART; + pHif->uartFcCtrl = ((hifconf & 0xc) >> 2); + val = (hifconf >> 8); + pHif->au4HifConf[0] = val; + pHif->au4HifConf[1] = val; + mtk_wcn_stp_set_if_tx_type(STP_UART_IF_TX); + } + else if (STP_SDIO == val) { + pHif->hifType = WMT_HIF_SDIO; + mtk_wcn_stp_set_if_tx_type(STP_SDIO_IF_TX); + } + else { + WMT_WARN_FUNC("invalid stp mode: %u \n", val); + mtk_wcn_stp_set_if_tx_type(STP_MAX_IF_TX); + return -1; + } + + val = (hifconf & 0xF0) >> 4; + if (WMT_FM_COMM == val) { + pHif->au4StrapConf[0] = WMT_FM_COMM; + } + else if (WMT_FM_I2C == val) { + pHif->au4StrapConf[0] = WMT_FM_I2C; + } + else { + WMT_WARN_FUNC("invalid fm mode: %u \n", val); + return -2; + } + + WMT_INFO_FUNC("new hifType:%d, fcCtrl:%d, baud:%d, fm:%d \n", + pHif->hifType, + pHif->uartFcCtrl, + pHif->au4HifConf[0], + pHif->au4StrapConf[0]); + return 0; +} + + +P_WMT_HIF_CONF +wmt_lib_get_hif (VOID) +{ + return &gDevWmt.rWmtHifConf; +} + +UCHAR* +wmt_lib_get_cmd (VOID) +{ + if (osal_test_and_clear_bit(WMT_STAT_CMD, &gDevWmt.state)) { + return gDevWmt.cCmd; + } + return NULL; +} + +MTK_WCN_BOOL +wmt_lib_get_cmd_status (VOID) +{ + return osal_test_bit(WMT_STAT_CMD, &gDevWmt.state) ? + MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} + +#if CFG_WMT_PS_SUPPORT +INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime) +{ + gPsIdleTime = psIdleTime; + return gPsIdleTime; +} + +INT32 wmt_lib_ps_ctrl(UINT32 state) +{ + if (0 == state) + { + wmt_lib_ps_disable(); + gPsEnable = 0; + } + else + { + gPsEnable = 1; + wmt_lib_ps_enable(); + } + return 0; +} + + +INT32 wmt_lib_ps_enable(VOID) +{ + if(gPsEnable) + { + mtk_wcn_stp_psm_enable(gPsIdleTime); + } + return 0; +} + +INT32 wmt_lib_ps_disable(VOID) +{ + if(gPsEnable) + { + mtk_wcn_stp_psm_disable(); + } + + return 0; +} + +INT32 wmt_lib_ps_init(VOID) +{ + //mtk_wcn_stp_psm_register_wmt_cb(wmt_lib_ps_stp_cb); + return 0; +} + +INT32 wmt_lib_ps_deinit(VOID) +{ + //mtk_wcn_stp_psm_unregister_wmt_cb(); + return 0; +} + +static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action) +{ + P_OSAL_OP lxop; + MTK_WCN_BOOL bRet; + UINT32 u4Wait; + + lxop = wmt_lib_get_free_op(); + if (!lxop) + { + WMT_WARN_FUNC("get_free_lxop fail \n"); + return MTK_WCN_BOOL_FALSE; + } + + lxop->op.opId = WMT_OPID_PWR_SV; + lxop->op.au4OpData[0] = action; + lxop->op.au4OpData[1] = (UINT32) mtk_wcn_stp_psm_notify_stp; + u4Wait = 0; + bRet = wmt_lib_put_act_op(lxop); + return bRet; +} + +static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID) +{ + return wmt_lib_ps_action(SLEEP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID) +{ + return wmt_lib_ps_action(WAKEUP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID) +{ + return wmt_lib_ps_action(HOST_AWAKE); +} +//extern int g_block_tx; +static INT32 +wmt_lib_ps_handler ( + MTKSTP_PSM_ACTION_T action + ) +{ + INT32 ret; + + ret = 0; // TODO:[FixMe][George] initial value or compile warning? + //if(g_block_tx && (action == SLEEP)) + if ((0 != mtk_wcn_stp_coredump_start_get()) && (action == SLEEP)) + { + mtk_wcn_stp_psm_notify_stp(SLEEP); + return ret; + } + + /*MT662x Not Ready*/ + if (!mtk_wcn_stp_is_ready()) { + WMT_DBG_FUNC("MT662x Not Ready, Dont Send Sleep/Wakeup Command\n"); + mtk_wcn_stp_psm_notify_stp(ROLL_BACK); + return 0; + } + + if (SLEEP == action) { + WMT_DBG_FUNC("send op--------------------------------> sleep job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + ret = wmt_lib_ps_do_sleep(); + WMT_DBG_FUNC("enable host eirq \n"); + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_EN); + } + else { + //ret = mtk_wcn_stp_sdio_do_own_set(); + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl)(OWN_SET); + } + else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + if (!ret) { + mtk_wcn_stp_psm_notify_stp(SLEEP); + } + else if (ret == -2) { + mtk_wcn_stp_psm_notify_stp(ROLL_BACK); + WMT_WARN_FUNC("====================================[SDIO-PS] rollback due to tx busy ============================%%\n"); + } + else { + mtk_wcn_stp_psm_notify_stp(SLEEP); + WMT_ERR_FUNC("====================================[SDIO-PS] set own fails! ============================%%\n"); + } + } + + WMT_DBG_FUNC("send op<--------------------------------- sleep job\n"); + } + else if (WAKEUP == action) { + WMT_DBG_FUNC("send op --------------------------------> wake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq \n"); + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + ret = wmt_lib_ps_do_wakeup(); + } + else { + //ret = mtk_wcn_stp_sdio_do_own_clr(); + + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl)(OWN_CLR); + } + else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + if (!ret) { + mtk_wcn_stp_psm_notify_stp(WAKEUP); + } + else { + mtk_wcn_stp_psm_notify_stp(WAKEUP); + WMT_ERR_FUNC("====================================[SDIO-PS] set own back fails! ===============================%%\n"); + } + } + + WMT_DBG_FUNC("send op<--------------------------------- wake job\n"); + } + else if (HOST_AWAKE == action) { + WMT_DBG_FUNC("send op --------------------------------> host awake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq \n"); + //IRQ already disabled + //wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + ret = wmt_lib_ps_do_host_awake(); + } + else { + WMT_DBG_FUNC("[SDIO-PS] SDIO host awake! ####\n"); + + //ret = mtk_wcn_stp_sdio_do_own_clr(); + + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl)(OWN_CLR); + } + else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + //Here we set ret to 0 directly + ret = 0; + if (!ret) { + mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); + } + else { + mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); + WMT_ERR_FUNC("====================================[SDIO-PS]set own back fails! ===============================%%\n"); + } + } + + WMT_DBG_FUNC("send op<--------------------------------- host awake job\n"); + } + else if (EIRQ == action) { + WMT_DBG_FUNC("send op --------------------------------> eirq job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq \n"); + //Disable interrupt + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + ret = mtk_wcn_stp_psm_notify_stp(EIRQ); + } + else { + WMT_ERR_FUNC("[SDIO-PS]sdio own-back eirq!######\n"); + ret = mtk_wcn_stp_psm_notify_stp(EIRQ); + } + + WMT_DBG_FUNC("send op<--------------------------------- eirq job\n"); + } + + return ret; +} +#endif /* end of CFG_WMT_PS_SUPPORT */ + +INT32 +wmt_lib_ps_stp_cb ( + MTKSTP_PSM_ACTION_T action + ) +{ +#if CFG_WMT_PS_SUPPORT + return wmt_lib_ps_handler(action); +#else + WMT_WARN_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); + return 0; +#endif +} + + +MTK_WCN_BOOL wmt_lib_is_quick_ps_support (VOID) +{ + return wmt_core_is_quick_ps_support(); +} + +VOID +wmt_lib_ps_irq_cb (VOID) +{ +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_handler(EIRQ); +#else + WMT_DBG_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); + return ; +#endif +} + + + +VOID +wmt_lib_ps_set_sdio_psop ( + PF_WMT_SDIO_PSOP own_cb + ) +{ +#if CFG_WMT_PS_SUPPORT + sdio_own_ctrl = own_cb; +#endif +} + +UINT32 wmt_lib_wait_event_checker(P_OSAL_THREAD pThread) +{ + P_DEV_WMT pDevWmt; + if (pThread) { + pDevWmt = (P_DEV_WMT)(pThread->pThreadData); + return (!RB_EMPTY(&pDevWmt->rActiveOpQ)); + } + else { + WMT_ERR_FUNC("pThread(NULL)\n"); + return 0; + } +} + +static INT32 wmtd_thread (void *pvData) +{ + P_DEV_WMT pWmtDev = (P_DEV_WMT)pvData; + P_OSAL_EVENT pEvent = NULL; + P_OSAL_OP pOp; + INT32 iResult; + + if (NULL == pWmtDev) { + WMT_ERR_FUNC("pWmtDev(NULL)\n"); + return -1; + } + WMT_INFO_FUNC("wmtd thread starts\n"); + + pEvent = &(pWmtDev->rWmtdWq); + + for (;;) { + pOp = NULL; + pEvent->timeoutValue = 0; +/* osal_thread_wait_for_event(&pWmtDev->thread, pEvent);*/ + osal_thread_wait_for_event(&pWmtDev->thread, pEvent, wmt_lib_wait_event_checker); + + if (osal_thread_should_stop(&pWmtDev->thread)) { + WMT_INFO_FUNC("wmtd thread should stop now... \n"); + // TODO: clean up active opQ + break; + } + + /* get Op from activeQ */ + pOp = wmt_lib_get_op(&pWmtDev->rActiveOpQ); + if (!pOp) { + WMT_WARN_FUNC("get_lxop activeQ fail\n"); + continue; + } +#if 0 //wmt_core_opid_handler will do sanity check on opId, so no usage here + id = lxop_get_opid(pLxOp); + if (id >= WMT_OPID_MAX) { + WMT_WARN_FUNC("abnormal opid id: 0x%x \n", id); + iResult = -1; + goto handlerDone; + } +#endif + + if (osal_test_bit(WMT_STAT_RST_ON, &pWmtDev->state)) { + /* when whole chip reset, only HW RST and SW RST cmd can execute*/ + if ((pOp->op.opId == WMT_OPID_HW_RST) + || (pOp->op.opId == WMT_OPID_SW_RST) + || (pOp->op.opId == WMT_OPID_GPIO_STATE)) { + iResult = wmt_core_opid(&pOp->op); + } else { + iResult = -2; + WMT_WARN_FUNC("Whole chip resetting, opid (0x%x) failed, iRet(%d)\n", pOp->op.opId,iResult); + } + } else { + wmt_lib_set_current_op(pWmtDev, pOp); + iResult = wmt_core_opid(&pOp->op); + wmt_lib_set_current_op(pWmtDev, NULL); + } + + if (iResult) { + WMT_WARN_FUNC("opid (0x%x) failed, iRet(%d)\n", pOp->op.opId,iResult); + } + + if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, iResult); + } + else { + /* put Op back to freeQ */ + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } + + if (WMT_OPID_EXIT == pOp->op.opId) { + WMT_INFO_FUNC("wmtd thread received exit signal\n"); + break; + } + } + + WMT_INFO_FUNC("wmtd thread exits succeed\n"); + + return 0; +}; + + +static MTK_WCN_BOOL wmt_lib_put_op ( + P_OSAL_OP_Q pOpQ, + P_OSAL_OP pOp + ) +{ + INT32 iRet; + + if (!pOpQ || !pOp) { + WMT_WARN_FUNC("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", pOpQ, pOp); + osal_assert(pOpQ); + osal_assert(pOp); + return MTK_WCN_BOOL_FALSE; + } + + iRet = osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + WMT_WARN_FUNC("osal_lock_sleepable_lock iRet(%d) \n", iRet); + return MTK_WCN_BOOL_FALSE; + } + + /* acquire lock success */ + if (!RB_FULL(pOpQ)) { + RB_PUT(pOpQ, pOp); + } + else { + iRet = -1; + } + osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (iRet) { + WMT_WARN_FUNC("RB_FULL(0x%p) \n", pOpQ); + return MTK_WCN_BOOL_FALSE; + } + else { + return MTK_WCN_BOOL_TRUE; + } +} + + + +static P_OSAL_OP wmt_lib_get_op ( + P_OSAL_OP_Q pOpQ + ) +{ + P_OSAL_OP pOp; + INT32 iRet; + + if (NULL == pOpQ) { + WMT_ERR_FUNC("pOpQ = NULL\n"); + osal_assert(pOpQ); + return NULL; + } + + iRet = osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + WMT_ERR_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); + return NULL; + } + + /* acquire lock success */ + RB_GET(pOpQ, pOp); + osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (NULL == pOp) { + WMT_WARN_FUNC("RB_GET return NULL\n"); + osal_assert(pOp); + } + + return pOp; +} + + +INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + if (MTK_WCN_BOOL_FALSE == wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp)) { + return -1; + } else { + return 0; + } +} + + +P_OSAL_OP wmt_lib_get_free_op (VOID) +{ + P_OSAL_OP pOp = NULL; + P_DEV_WMT pDevWmt = &gDevWmt; + + osal_assert(pDevWmt); + + if (NULL != pDevWmt) { + pOp = wmt_lib_get_op(&pDevWmt->rFreeOpQ); + if (pOp) { + osal_memset(&pOp->op, 0, osal_sizeof(pOp->op)); + } + return pOp; + } + else { + return NULL; + } +} + +MTK_WCN_BOOL wmt_lib_put_act_op (P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + MTK_WCN_BOOL bCleanup = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal = NULL; + LONG waitRet = -1; + + osal_assert(pWmtDev); + osal_assert(pOp); + + do { + if (!pWmtDev || !pOp) { + WMT_ERR_FUNC("pWmtDev(0x%p), pOp(0x%p)\n", pWmtDev, pOp); + break; + } + if(0 != mtk_wcn_stp_coredump_start_get()) + { + bCleanup = MTK_WCN_BOOL_TRUE; + WMT_WARN_FUNC("block tx flag is set\n"); + break; + } + pSignal = &pOp->signal; +// pOp->u4WaitMs = u4WaitMs; + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(pSignal); + } + + /* put to active Q */ + bRet = wmt_lib_put_op(&pWmtDev->rActiveOpQ, pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("put to active queue fail\n"); + bCleanup = MTK_WCN_BOOL_TRUE; + break; + } + + /* wake up wmtd */ + //wake_up_interruptible(&pWmtDev->rWmtdWq); + osal_trigger_event(&pWmtDev->rWmtdWq); + + if (0 == pSignal->timeoutValue) { + bRet = MTK_WCN_BOOL_TRUE; + /* clean it in wmtd */ + break; + } + /* wait result, clean it here */ + bCleanup = MTK_WCN_BOOL_TRUE; + + /* check result */ + //wait_ret = wait_for_completion_interruptible_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); + //wait_ret = wait_for_completion_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); + waitRet = osal_wait_for_signal_timeout(pSignal); + WMT_DBG_FUNC("osal_wait_for_signal_timeout:%ld\n", waitRet); + + //if (unlikely(!wait_ret)) { + if (0 == waitRet) + { + WMT_ERR_FUNC("wait completion timeout\n"); + // TODO: how to handle it? retry? + } + else { + if (pOp->result) { + WMT_WARN_FUNC("opId(%d) result:%d\n", pOp->op.opId, pOp->result); + } + } + /* op completes, check result */ + bRet = (pOp->result) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; + } while(0); + + if (bCleanup) { + /* put Op back to freeQ */ + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } + + return bRet; +} + +// TODO:[ChangeFeature][George] is this function obsoleted? +#if 0 +INT32 wmt_lib_reg_rw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pvalue, + UINT32 mask + ) +{ + P_WMT_LXOP lxop; + MTK_WCN_BOOL bRet; + PUINT32 plv = NULL; + UINT32 pbuf[2]; + P_OSAL_EVENT pSignal = NULL; + if (!pvalue) { + WMT_WARN_FUNC("!pvalue \n"); + return -1; + } + lxop = wmt_lib_get_free_lxop(); + if (!lxop) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + + return -1; + } + + plv = (PUINT32)(((UINT32)pbuf + 0x3) & ~0x3UL); + *plv = *pvalue; + pSignal = &lxop->signal; + WMT_DBG_FUNC("OPID_REG_RW isWrite(%d) offset(0x%x) value(0x%x) mask(0x%x)\n", + isWrite, offset, *pvalue, mask); + + lxop->op.opId = WMT_OPID_REG_RW; + lxop->op.au4OpData[0] = isWrite; + lxop->op.au4OpData[1] = offset; + lxop->op.au4OpData[2] = (UINT32)plv; + lxop->op.au4OpData[3] = mask; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + DISABLE_PSM_MONITOR(); + bRet = wmt_lib_put_act_lxop(lxop); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, *plv, mask); + if (!isWrite) { + *pvalue = *plv; + } + } + else { + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, *plv, mask, bRet); + } + + return bRet; +} +#endif + +// TODO:[ChangeFeature][George] is this function obsoleted? +#if 0 +static VOID wmt_lib_clear_chip_id(VOID) +{ +/* + gDevWmt.pChipInfo = NULL; +*/ + gDevWmt.hw_ver = WMTHWVER_INVALID; + + return; +} +#endif + +// TODO: [FixMe][GeorgeKuo]: change this API to report real chip id, hw_ver, and +// fw_ver instead of WMT-translated WMTHWVER +ENUM_WMTHWVER_TYPE_T +wmt_lib_get_hwver (VOID) +{ +/* + P_WMT_CMB_CHIP_INFO_S pChipInfo = NULL; + P_DEV_WMT pWmtDev = gpDevWmt; + pChipInfo = wmt_lib_get_chip_info(pWmtDev); + return pChipInfo != NULL ? pChipInfo->eHwVersion : WMTHWVER_INVALID; + */ + return gDevWmt.eWmtHwVer; +} + +UINT32 +wmt_lib_get_icinfo (ENUM_WMT_CHIPINFO_TYPE_T index) +{ + if (WMTCHIN_CHIPID == index) + { + return gDevWmt.chip_id; + } + else if (WMTCHIN_HWVER == index) + { + return gDevWmt.hw_ver; + } + else if (WMTCHIN_MAPPINGHWVER == index) + { + return gDevWmt.eWmtHwVer; + } + else if (WMTCHIN_FWVER == index) + { + return gDevWmt.fw_ver; + } + return 0; + +} + + +UCHAR* wmt_lib_def_patch_name (VOID) +{ + WMT_INFO_FUNC("wmt-lib: use default patch name (%s)\n", gDevWmt.cPatchName); + return gDevWmt.cPatchName; +} + + +MTK_WCN_BOOL +wmt_lib_is_therm_ctrl_support (VOID) +{ + MTK_WCN_BOOL bIsSupportTherm = MTK_WCN_BOOL_TRUE; + // TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file + if ( ((0x6620 == gDevWmt.chip_id) && (WMTHWVER_MT6620_E3 > gDevWmt.eWmtHwVer)) + || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer) ) { + WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); + bIsSupportTherm = MTK_WCN_BOOL_FALSE; + } + if(!mtk_wcn_stp_is_ready()) + { + WMT_ERR_FUNC("thermal command can not be send: STP is not ready\n"); + bIsSupportTherm = MTK_WCN_BOOL_FALSE; + } + + return bIsSupportTherm; +} + +MTK_WCN_BOOL +wmt_lib_is_dsns_ctrl_support (VOID) +{ + // TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file + if ( ((0x6620 == gDevWmt.chip_id) && (WMTHWVER_MT6620_E3 > gDevWmt.eWmtHwVer)) + || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer) ) { + WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); + return MTK_WCN_BOOL_FALSE; + } + + return MTK_WCN_BOOL_TRUE; +} + + +/*! + * \brief Update combo chip pin settings (GPIO) + * + * An internal library function to support various settings for chip GPIO. It is + * updated in a grouping way: configure all required pins in a single call. + * + * \param id desired pin ID to be controlled + * \param stat desired pin states to be set + * \param flag supplementary options for this operation + * + * \retval 0 operation success + * \retval -1 invalid id + * \retval -2 invalid stat + * \retval < 0 error for operation fail + */ +static INT32 wmt_lib_pin_ctrl (WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /* input sanity check */ + if (WMT_IC_PIN_MAX <= id) { + WMT_ERR_FUNC("invalid ic pin id(%d)\n", id); + return -1; + } + if (WMT_IC_PIN_STATE_MAX <= stat) { + WMT_ERR_FUNC("invalid ic pin state (%d)\n", stat); + return -2; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_GPIO_CTRL (ic pin id:%d, stat:%d, flag:0x%x)\n", id, stat, flag); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_GPIO_CTRL; + pOp->op.au4OpData[0] = id; + pOp->op.au4OpData[1] = stat; + pOp->op.au4OpData[2] = flag; + pSignal->timeoutValue= MAX_EACH_WMT_CMD; + + /*wake up chip first*/ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("PIN_ID(%d) PIN_STATE(%d) flag(%d) fail\n", id, stat, flag); + } + else { + WMT_DBG_FUNC("OPID(%d) type(%d) ok\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + } + + return 0; +} + +INT32 wmt_lib_reg_rw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pvalue, + UINT32 mask + ) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 value; + P_OSAL_SIGNAL pSignal; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue \n"); + return -1; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + value = *pvalue; + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", + isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_REG_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (UINT32)&value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) { + *pvalue = value; + } + return 0; + } + else { + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + return -1; + } +} + +INT32 wmt_lib_efuse_rw ( + UINT32 isWrite, + UINT32 offset, + PUINT32 pvalue, + UINT32 mask + ) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 value; + P_OSAL_SIGNAL pSignal; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue \n"); + return -1; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + value = *pvalue; + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", + isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_EFUSE_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (UINT32)&value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) { + *pvalue = value; + } + return 0; + } + else { + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + return -1; + } +} + + + + +/*! + * \brief update combo chip AUDIO Interface (AIF) settings + * + * A library function to support updating chip AUDIO pin settings. A group of + * pins is updated as a whole. + * + * \param aif desired audio interface state to use + * \param flag whether audio pin is shared or not + * + * \retval 0 operation success + * \retval -1 invalid aif + * \retval < 0 error for invalid parameters or operation fail + */ +INT32 wmt_lib_set_aif (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share) +{ + if (CMB_STUB_AIF_MAX <= aif) { + WMT_ERR_FUNC("invalid aif (%d) \n", aif); + return -1; + } + WMT_DBG_FUNC("call pin_ctrl for aif:%d, share:%d \n", aif, (MTK_WCN_BOOL_TRUE == share) ? 1:0); + /* Translate CMB_STUB_AIF_X into WMT_IC_PIN_STATE by array */ + return wmt_lib_pin_ctrl(WMT_IC_PIN_AUDIO, + cmb_aif2pin_stat[aif], + (MTK_WCN_BOOL_TRUE == share) ? WMT_LIB_AIF_FLAG_SHARE : WMT_LIB_AIF_FLAG_SEPARATE); +} + +INT32 wmt_lib_host_awake_get(VOID) +{ + return wmt_plat_wake_lock_ctrl(WL_OP_GET); +} +INT32 wmt_lib_host_awake_put(VOID) +{ + return wmt_plat_wake_lock_ctrl(WL_OP_PUT); +} + +MTK_WCN_BOOL wmt_lib_btm_cb (MTKSTP_BTM_WMT_OP_T op) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + if(op == BTM_RST_OP){ + //high priority, not to enqueue into the queue of wmtd + WMT_INFO_FUNC("Invoke whole chip reset from stp_btm!!!\n"); + wmt_lib_cmb_rst(WMTRSTSRC_RESET_STP); + bRet = MTK_WCN_BOOL_TRUE; + } else if(op == BTM_DMP_OP){ + + WMT_WARN_FUNC("TBD!!!\n"); + } + else if (op == BTM_GET_AEE_SUPPORT_FLAG) + { + bRet = wmt_core_get_aee_dump_flag(); + } + return bRet; +} + +MTK_WCN_BOOL wmt_cdev_rstmsg_snd(ENUM_WMTRSTMSG_TYPE_T msg){ + + INT32 i = 0; + P_DEV_WMT pDevWmt = &gDevWmt; + UCHAR *drv_name[] = { + "DRV_TYPE_BT", + "DRV_TYPE_FM" , + "DRV_TYPE_GPS", + "DRV_TYPE_WIFI" + }; + + for(i = 0 ; i <= WMTDRV_TYPE_WIFI; i++){ + //<1> check if reset callback is registered + if(pDevWmt->rFdrvCb.fDrvRst[i]){ + //<2> send the msg to this subfucntion + /*src, dst, msg_type, msg_data, msg_size*/ + pDevWmt->rFdrvCb.fDrvRst[i](WMTDRV_TYPE_WMT, i, WMTMSG_TYPE_RESET, &msg, sizeof(ENUM_WMTRSTMSG_TYPE_T)); + WMT_INFO_FUNC("type = %s, msg sent\n", drv_name[i]); + } else { + WMT_DBG_FUNC("type = %s, unregistered\n", drv_name[i]); + } + } + + return MTK_WCN_BOOL_TRUE; +} + +VOID wmt_lib_state_init(VOID) +{ + //UINT32 i = 0; + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + + /* Initialize op queue */ + //RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); + //RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); + + while ((pOp = wmt_lib_get_op(&pDevWmt->rActiveOpQ))) { + osal_signal_init(&(pOp->signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); + } + + /* Put all to free Q */ + /* + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_init(&(pDevWmt->arQue[i].signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); + }*/ + return; +} + + +INT32 wmt_lib_sdio_ctrl(UINT32 on) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_SDIO_CTRL\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_SDIO_CTRL; + pOp->op.au4OpData[0] = on; + pSignal->timeoutValue= MAX_GPIO_CTRL_TIME; + + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_SDIO_CTRL failed\n"); + return -1; + } + else { + WMT_DBG_FUNC("OPID(WMT_OPID_SDIO_CTRL)ok\n"); + } + return 0; +} + +MTK_WCN_BOOL wmt_lib_hw_state_show(VOID) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_HW_STATE_SHOW\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_GPIO_STATE; + pSignal->timeoutValue= MAX_GPIO_CTRL_TIME; + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_HW_STATE_SHOW failed\n"); + return MTK_WCN_BOOL_FALSE; + } + else { + WMT_DBG_FUNC("OPID(WMT_OPID_HW_STATE_SHOW)ok\n"); + } + return MTK_WCN_BOOL_TRUE; +} + + +MTK_WCN_BOOL wmt_lib_hw_rst(VOID){ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + P_DEV_WMT pDevWmt = &gDevWmt; + + wmt_lib_state_init(); + + osal_clear_bit(WMT_STAT_STP_REG, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_OPEN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_EN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_RDY, &pDevWmt->state); + osal_clear_bit(WMT_STAT_RX, &pDevWmt->state); + osal_clear_bit(WMT_STAT_CMD, &pDevWmt->state); + + /*Before do hardware reset, we show GPIO state to check if others modified our pin state accidentially*/ + wmt_lib_hw_state_show(); + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_HW_RST\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_HW_RST; + pSignal->timeoutValue= MAX_GPIO_CTRL_TIME; + + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_HW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + else { + WMT_DBG_FUNC("OPID(WMT_OPID_HW_RST)ok\n"); + } + return MTK_WCN_BOOL_TRUE; +} + +MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + //<1> wmt state reset + wmt_lib_state_init(); + + //<2> Reset STP data structure + WMT_DBG_FUNC("Cleanup STP context\n"); + mtk_wcn_stp_flush_context(); + //<3> Reset STP-PSM data structure + WMT_DBG_FUNC("Cleanup STP-PSM context\n"); + mtk_wcn_stp_psm_reset(); + + //<4> do sw reset in wmt-core + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_SW_RST \n"); + + pSignal = &pOp->signal; + pSignal->timeoutValue= MAX_FUNC_ON_TIME; + + pOp->op.opId = WMT_OPID_SW_RST; + pOp->op.au4OpData[0] = baudRst; + + + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_SW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + else { + WMT_DBG_FUNC("OPID(WMT_OPID_SW_RST)ok\n"); + } + return MTK_WCN_BOOL_TRUE; +} + + +ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src){ + #define RETRYTIMES 10 + MTK_WCN_BOOL bRet; + ENUM_WMTRSTRET_TYPE_T retval = WMTRSTRET_MAX; + INT32 retries = RETRYTIMES; + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + UCHAR *srcName[]={"WMTRSTSRC_RESET_BT", + "WMTRSTSRC_RESET_FM", + "WMTRSTSRC_RESET_GPS", + "WMTRSTSRC_RESET_WIFI", + "WMTRSTSRC_RESET_STP", + "WMTRSTSRC_RESET_TEST" }; + + if(src < WMTRSTSRC_RESET_MAX){ + WMT_INFO_FUNC("reset source = %s\n", srcName[src]); + } + + if (WMTRSTSRC_RESET_TEST == src) { + pOp = wmt_lib_get_current_op(pDevWmt); + if (pOp && ((WMT_OPID_FUNC_ON == pOp->op.opId) + || (WMT_OPID_FUNC_OFF == pOp->op.opId))) { + WMT_INFO_FUNC("can't do reset by test src when func on/off\n"); + return -1; + } + } + + //<1> Consider the multi-context combo_rst case. + if (osal_test_and_set_bit(WMT_STAT_RST_ON, &pDevWmt->state)) { + retval = WMTRSTRET_ONGOING; + goto rstDone; + } + //<2> Block all STP request + mtk_wcn_stp_enable(0); + + //<3> RESET_START notification + bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_START); + if(bRet == MTK_WCN_BOOL_FALSE){ + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd! \n"); + retval = WMTRSTRET_FAIL; + goto rstDone; + } + + // wakeup blocked opid + pOp = wmt_lib_get_current_op(pDevWmt); + if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, -1); + } + + // wakeup blocked cmd + wmt_dev_rx_event_cb(); + + //<4> retry until reset flow successful + while(retries > 0){ + //<4.1> reset combo hw + bRet = wmt_lib_hw_rst(); + if(bRet == MTK_WCN_BOOL_FALSE){ + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_hw_rst! \n"); + retries--; + continue; + } + + //<4.2> reset driver/combo sw + bRet = wmt_lib_sw_rst(1); + if(bRet == MTK_WCN_BOOL_FALSE){ + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_sw_rst! \n"); + retries--; + continue; + } + break; + } + + if(bRet == MTK_WCN_BOOL_FALSE){ + WMT_INFO_FUNC("[whole chip reset] fail! retries = %d\n", RETRYTIMES-retries); + retval = WMTRSTRET_FAIL; + goto rstDone; + } else { + WMT_INFO_FUNC("[whole chip reset] ok! retries = %d\n", RETRYTIMES-retries); + } + + + //<5> RESET_END notification + bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_END); + if(bRet == MTK_WCN_BOOL_FALSE){ + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd! \n"); + retval = WMTRSTRET_FAIL; + goto rstDone; + } + + retval = WMTRSTRET_SUCCESS; +rstDone: + osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state); + return retval; +} + + +MTK_WCN_BOOL wmt_lib_msgcb_reg ( + ENUM_WMTDRV_TYPE_T eType, + PF_WMT_CB pCb + ) +{ + + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_DEV_WMT pWmtDev = &gDevWmt; + + if(eType >= 0 && eType <= WMTDRV_TYPE_WIFI){ + WMT_DBG_FUNC("reg ok! \n"); + pWmtDev->rFdrvCb.fDrvRst[eType] = pCb; + bRet = MTK_WCN_BOOL_TRUE; + } else { + WMT_WARN_FUNC("reg fail! \n") + } + + return bRet; +} + +MTK_WCN_BOOL wmt_lib_msgcb_unreg ( + ENUM_WMTDRV_TYPE_T eType + ) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_DEV_WMT pWmtDev = &gDevWmt; + + if(eType >= 0 && eType <= WMTDRV_TYPE_WIFI){ + WMT_DBG_FUNC("unreg ok! \n"); + pWmtDev->rFdrvCb.fDrvRst[eType] = NULL; + bRet = MTK_WCN_BOOL_TRUE; + } else { + WMT_WARN_FUNC("unreg fail! \n") + } + + return bRet; +} + + +UINT32 wmt_lib_dbg_level_set(UINT32 level) +{ + gWmtDbgLvl = level > WMT_LOG_LOUD ? WMT_LOG_LOUD : level; + return 0; +} + + +INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value) +{ + return mtk_wcn_stp_set_wmt_last_close(value); +} + + +INT32 wmt_lib_notify_stp_sleep() +{ + INT32 iRet = 0x0; + + iRet = wmt_lib_psm_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock psm_lock failed, iRet=%d\n", iRet); + return iRet; + } + + iRet = mtk_wcn_stp_notify_sleep_for_thermal(); + wmt_lib_psm_lock_release(); + + return iRet; +} + + +VOID wmt_lib_set_patch_num(ULONG num) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + pWmtDev->patchNum = num; +} + + +VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + if (pPatchinfo) { + pWmtDev->pWmtPatchInfo = pPatchinfo; + } +} + + +INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp) +{ + if (pWmtDev) { + pWmtDev->pCurOP = pOp; + WMT_DBG_FUNC("pOp=0x%p\n", pOp); + return 0; + } else { + WMT_ERR_FUNC("Invalid pointer\n"); + return -1; + } +} + + +P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev) + { + if (pWmtDev) { + return pWmtDev->pCurOP; + } else { + WMT_ERR_FUNC("Invalid pointer\n"); + return NULL; + } +} + +INT32 wmt_lib_merge_if_flag_ctrl(UINT32 enable) +{ +#if WMT_PLAT_ALPS + return wmt_plat_merge_if_flag_ctrl(enable); +#endif +} + + +INT32 wmt_lib_merge_if_flag_get(UINT32 enable) +{ +#if WMT_PLAT_ALPS + return wmt_plat_merge_if_flag_get(); +#endif +} + diff --git a/drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h b/drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h new file mode 100755 index 000000000000..4724dbf587c0 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h @@ -0,0 +1,90 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _MTK_WCN_CMB_HW_H_ +#define _MTK_WCN_CMB_HW_H_ + +#include "osal_typedef.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _PWR_SEQ_TIME_ +{ + UINT32 rtcStableTime; + UINT32 ldoStableTime; + UINT32 rstStableTime; + UINT32 offStableTime; + UINT32 onStableTime; +}PWR_SEQ_TIME, *P_PWR_SEQ_TIME; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +extern INT32 mtk_wcn_cmb_hw_pwr_off (VOID); +extern INT32 mtk_wcn_cmb_hw_pwr_on (VOID); +extern INT32 mtk_wcn_cmb_hw_rst (VOID); +extern INT32 mtk_wcn_cmb_hw_init (P_PWR_SEQ_TIME pPwrSeqTime); +extern INT32 mtk_wcn_cmb_hw_deinit (VOID); +extern INT32 mtk_wcn_cmb_hw_state_show(VOID); + + +#endif /* _MTK_WCN_CMB_HW_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/include/stp_exp.h b/drivers/mtk_wcn_combo/common/include/stp_exp.h new file mode 100755 index 000000000000..97c1d9708ebb --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/stp_exp.h @@ -0,0 +1,227 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _STP_EXP_H_ +#define _STP_EXP_H_ + +#include "osal_typedef.h" +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define BT_TASK_INDX (0) +#define FM_TASK_INDX (1) +#define GPS_TASK_INDX (2) +#define WIFI_TASK_INDX (3) +#define WMT_TASK_INDX (4) +#define STP_TASK_INDX (5) +#define INFO_TASK_INDX (6) +#define MTKSTP_MAX_TASK_NUM (7) + +#define MTKSTP_BUFFER_SIZE (16384) //Size of RX Queue + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef void (*MTK_WCN_STP_EVENT_CB)(void); +typedef INT32 (*MTK_WCN_STP_IF_TX)(const UINT8 *data, const UINT32 size, UINT32 *written_size); +/* export for HIF driver */ +typedef void (*MTK_WCN_STP_IF_RX)(const UINT8 *data, INT32 size); + +typedef enum { + STP_UART_IF_TX = 0, + STP_SDIO_IF_TX, + STP_MAX_IF_TX +}ENUM_STP_TX_IF_TYPE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data(const UINT8 *buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* Is STP ready? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:ready, FALSE:not ready +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +extern INT32 mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length); + +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_tx_event_cb +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* func +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_event_cb +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* func +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_tx +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_rx +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_EXP_H_ */ + + + + + + + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/include/wmt.h b/drivers/mtk_wcn_combo/common/include/wmt.h new file mode 100755 index 000000000000..f4931871f339 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/wmt.h @@ -0,0 +1,8 @@ + +#ifndef _MTKWMT_H_ +#define _MTKWMT_H_ +#include "wmt_core.h" + + + +#endif /*_MTKWMT_H_*/ diff --git a/drivers/mtk_wcn_combo/common/include/wmt_exp.h b/drivers/mtk_wcn_combo/common/include/wmt_exp.h new file mode 100755 index 000000000000..466c97fcf54e --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/wmt_exp.h @@ -0,0 +1,257 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_EXP_H_ +#define _WMT_EXP_H_ + +#include +#include "osal.h" +//not to reference to internal wmt +//#include "wmt_core.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_LOUD_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_LOUD) { osal_dbg_print(DFT_TAG "[L]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_INFO_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_INFO) { osal_info_print(DFT_TAG "[I]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_WARN_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_WARN) { osal_warn_print(DFT_TAG "[W]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_ERR_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_ERR) { osal_err_print(DFT_TAG "[E]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} +#define WMT_DBG_FUNC(fmt, arg...) if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "[D]%s:" fmt, __FUNCTION__ ,##arg);} +#define WMT_TRC_FUNC(f) if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "<%s> <%d>\n", __FUNCTION__, __LINE__);} +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +extern UINT32 gWmtDbgLvl ; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#define WMT_LOG_LOUD 4 +#define WMT_LOG_DBG 3 +#define WMT_LOG_INFO 2 +#define WMT_LOG_WARN 1 +#define WMT_LOG_ERR 0 +#endif + +#define CFG_WMT_PS_SUPPORT 1 /* moved from wmt_lib.h */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_STP = 5, + WMTDRV_TYPE_SDIO1 = 6, + WMTDRV_TYPE_SDIO2 = 7, + WMTDRV_TYPE_LPBK = 8, + WMTDRV_TYPE_COREDUMP = 9, + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +// TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type +// TODO: how do we extend for new chip and newer revision? +// TODO: This way is hard to extend +typedef enum _ENUM_WMTHWVER_TYPE_T{ + WMTHWVER_MT6620_E1 = 0x0, + WMTHWVER_MT6620_E2 = 0x1, + WMTHWVER_MT6620_E3 = 0x2, + WMTHWVER_MT6620_E4 = 0x3, + WMTHWVER_MT6620_E5 = 0x4, + WMTHWVER_MT6620_E6 = 0x5, + WMTHWVER_MT6620_E7 = 0x6, + WMTHWVER_MT6620_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +typedef enum _ENUM_WMTCHIN_TYPE_T{ + WMTCHIN_CHIPID = 0x0, + WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, + WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, + WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, + WMTCHIN_MAX, + +}ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; + +typedef enum _ENUM_WMTDSNS_TYPE_T{ + WMTDSNS_FM_DISABLE = 0, + WMTDSNS_FM_ENABLE = 1, + WMTDSNS_FM_GPS_DISABLE = 2, + WMTDSNS_FM_GPS_ENABLE = 3, + WMTDSNS_MAX +} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; + +typedef enum _ENUM_WMTTHERM_TYPE_T{ + WMTTHERM_ZERO = 0, + WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, + WMTTHERM_READ = WMTTHERM_ENABLE + 1, + WMTTHERM_DISABLE = WMTTHERM_READ + 1, + WMTTHERM_MAX +}ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY= 3, + WMTMSG_TYPE_HW_FUNC_ON= 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + +typedef enum _ENUM_WMTRSTMSG_TYPE_T{ + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; + +typedef void (*PF_WMT_CB)( + ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + VOID *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client + can't touch this buffer after this function return. */ + UINT32 /* Buffer size in unit of byte */ +); + +typedef enum _SDIO_PS_OP{ + OWN_SET = 0, + OWN_CLR = 1, + OWN_STATE = 2, +} SDIO_PS_OP; + + +typedef INT32 (*PF_WMT_SDIO_PSOP)(SDIO_PS_OP); + +#if 1 /* moved from wmt_core.h */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1*/ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*subsystem function ctrl APIs*/ +extern MTK_WCN_BOOL +mtk_wcn_wmt_func_off ( + ENUM_WMTDRV_TYPE_T type + ); + +extern MTK_WCN_BOOL +mtk_wcn_wmt_func_on ( + ENUM_WMTDRV_TYPE_T type + ); + +extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl ( + ENUM_WMTDSNS_TYPE_T eType + ); + +extern MTK_WCN_BOOL mtk_wcn_wmt_assert ( + VOID + ); + +extern INT32 mtk_wcn_wmt_msgcb_reg ( + ENUM_WMTDRV_TYPE_T eType, + PF_WMT_CB pCb + ); + +extern INT32 mtk_wcn_wmt_msgcb_unreg ( + ENUM_WMTDRV_TYPE_T eType + ); + +extern INT32 +mtk_wcn_stp_wmt_sdio_op_reg ( + PF_WMT_SDIO_PSOP own_cb + ); + +extern INT32 +mtk_wcn_stp_wmt_sdio_host_awake( + VOID + ); +/* +return value: +enable/disable thermal sensor function: true(1)/false(0) +read thermal sensor function: thermal value + +*/ +extern INT8 +mtk_wcn_wmt_therm_ctrl ( + ENUM_WMTTHERM_TYPE_T eType + ); + +extern ENUM_WMTHWVER_TYPE_T +mtk_wcn_wmt_hwver_get (VOID); + +extern INT32 +mtk_wcn_wmt_chipid_query (VOID); + + +extern INT32 wmt_lib_set_aif ( + CMB_STUB_AIF_X aif, + MTK_WCN_BOOL share + ); /* set AUDIO interface options */ +extern VOID +wmt_lib_ps_irq_cb(VOID); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_EXP_H_ */ + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/include/wmt_plat.h b/drivers/mtk_wcn_combo/common/include/wmt_plat.h new file mode 100755 index 000000000000..3cf5440c3622 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/wmt_plat.h @@ -0,0 +1,212 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_PLAT_H_ +#define _WMT_PLAT_H_ +#include "osal_typedef.h" +#include "osal.h" +#include +#include "mtk_wcn_cmb_hw.h" + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + + +#if (CONFIG_ARCH_MT6589) + #if defined(MTK_MERGE_INTERFACE_SUPPORT) && defined(MT6628) + #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 1 + #else + #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 0 + #endif +#else + #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 0 +#endif + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#if 0 /* [GeorgeKuo] remove COMBO_AUDIO FLAG */ +#define COMBO_AUDIO_BT_MASK (0x1UL) +#define COMBO_AUDIO_BT_PCM_ON (0x1UL << 0) +#define COMBO_AUDIO_BT_PCM_OFF (0x0UL << 0) + +#define COMBO_AUDIO_FM_MASK (0x2UL) +#define COMBO_AUDIO_FM_LINEIN (0x0UL << 1) +#define COMBO_AUDIO_FM_I2S (0x1UL << 1) + +#define COMBO_AUDIO_PIN_MASK (0x4UL) +#define COMBO_AUDIO_PIN_SHARE (0x1UL << 2) +#define COMBO_AUDIO_PIN_SEPARATE (0x0UL << 2) +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_FUNC_STATE_{ + FUNC_ON = 0, + FUNC_OFF = 1, + FUNC_RST = 2, + FUNC_STAT = 3, + FUNC_CTRL_MAX, +} ENUM_FUNC_STATE, *P_ENUM_FUNC_STATE; + +typedef enum _ENUM_PIN_ID_{ + PIN_LDO = 0, + PIN_PMU = 1, + PIN_RTC = 2, + PIN_RST = 3, + PIN_BGF_EINT = 4, + PIN_WIFI_EINT = 5, + PIN_ALL_EINT = 6, + PIN_UART_GRP = 7, + PIN_PCM_GRP = 8, + PIN_I2S_GRP = 9, + PIN_SDIO_GRP = 10, + PIN_GPS_SYNC = 11, + PIN_GPS_LNA = 12, + PIN_ID_MAX +} ENUM_PIN_ID, *P_ENUM_PIN_ID; + +typedef enum _ENUM_PIN_STATE_{ + PIN_STA_INIT = 0, + PIN_STA_OUT_L = 1, + PIN_STA_OUT_H = 2, + PIN_STA_IN_L = 3, + PIN_STA_MUX = 4, + PIN_STA_EINT_EN = 5, + PIN_STA_EINT_DIS = 6, + PIN_STA_DEINIT = 7, + PIN_STA_SHOW = 8, + PIN_STA_MAX +} ENUM_PIN_STATE, *P_ENUM_PIN_STATE; + +typedef enum _CMB_IF_TYPE_{ + CMB_IF_UART = 0, + CMB_IF_WIFI_SDIO = 1, + CMB_IF_BGF_SDIO = 2, + CMB_IF_BGWF_SDIO = 3, + CMB_IF_TYPE_MAX +} CMB_IF_TYPE, *P_CMB_IF_TYPE; + +typedef INT32 (*fp_set_pin)(ENUM_PIN_STATE); + +typedef enum _ENUM_WL_OP_{ + WL_OP_GET = 0, + WL_OP_PUT = 1, + WL_OP_MAX +} ENUM_WL_OP, *P_ENUM_WL_OP; + +typedef VOID (*irq_cb)(VOID); +typedef INT32 (*device_audio_if_cb) (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 +wmt_plat_init (P_PWR_SEQ_TIME pPwrSeqTime); + +INT32 +wmt_plat_deinit (VOID); + +INT32 +wmt_plat_irq_ctrl ( + ENUM_FUNC_STATE state + ); + +INT32 +wmt_plat_pwr_ctrl ( + ENUM_FUNC_STATE state + ); + +INT32 +wmt_plat_ps_ctrl ( + ENUM_FUNC_STATE state + ); + +INT32 +wmt_plat_gpio_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ); + +INT32 +wmt_plat_eirq_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ); + +INT32 +wmt_plat_sdio_ctrl ( + UINT32 sdioPortNum, + ENUM_FUNC_STATE on + ); + + +INT32 +wmt_plat_wake_lock_ctrl( + ENUM_WL_OP opId + ); + +VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb); + +INT32 +wmt_plat_audio_ctrl ( + CMB_STUB_AIF_X state, + CMB_STUB_AIF_CTRL ctrl + ); + +VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb); + +INT32 +wmt_plat_merge_if_flag_ctrl (UINT32 enagle); + +INT32 +wmt_plat_merge_if_flag_get (VOID); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_PLAT_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h b/drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h new file mode 100755 index 000000000000..ba2f26eaf6e4 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h @@ -0,0 +1,13 @@ +#ifndef _WMT_PLAT_STUB_H_ +#define _WMT_PLAT_STUB_H_ + + +INT32 +wmt_plat_audio_ctrl ( + CMB_STUB_AIF_X state, + CMB_STUB_AIF_CTRL ctrl + ); + +INT32 wmt_plat_stub_init (void); + +#endif /*_WMT_PLAT_STUB_H_*/ \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/common/linux/hif_sdio.c b/drivers/mtk_wcn_combo/common/linux/hif_sdio.c new file mode 100755 index 000000000000..b30318709365 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/hif_sdio.c @@ -0,0 +1,2491 @@ +/* +** $Id: $ +*/ + +/*! \file "hif_sdio.c" + * \brief + * + * detailed description +*/ + +/* +** $Log: $ + * + * 07 25 2010 george.kuo + * + * Move hif_sdio driver to linux directory. + * + * 07 23 2010 george.kuo + * + * Add MT6620 driver source tree + * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver. +** +** +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_SDIO_UPDATE (1) +#if (WMT_PLAT_APEX==1) +#define HIF_SDIO_SUPPORT_SUSPEND (1) +#else +#define HIF_SDIO_SUPPORT_SUSPEND (0) +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +#include "hif_sdio.h" +#include "hif_sdio_chrdev.h" + +#if 0 +extern void mmc_power_up_ext(struct mmc_host *host); +extern void mmc_power_off_ext(struct mmc_host *host); +#else +#define mmc_power_up_ext(x) +#define mmc_power_off_ext(x) + +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//#define DRV_NAME "[hif_sdio]" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*! + * \brief A macro used to generate hif_sdio client's context + * + * Generate a context for hif_sdio client based on the following input parameters + * |<-card id (16bits)->|<-block size in unit of 256 bytes(8 bits)->|<-function number(4bits)->|<-index(4bits)->| + * + * \param manf the 16 bit manufacturer id + * \param card the 16 bit card id + * \param func the 16 bit function number + * \param b_sz the 16 bit function block size + */ +#define CLTCTX(cid, func, blk_sz, idx) \ + (MTK_WCN_HIF_SDIO_CLTCTX)( (((UINT32)(cid) & 0xFFFFUL) << 16) | \ + (((UINT32)(func) & 0xFUL) << 4) | \ + (((UINT32)(blk_sz) & 0xFF00UL) << 0) | \ + (((UINT32)idx & 0xFUL) << 0) ) + +/*! + * \brief A set of macros used to get information out of an hif_sdio client context + * + * Generate a context for hif_sdio client based on the following input parameters + */ +#define CLTCTX_CID(ctx) (((ctx) >> 16) & 0xFFFF) +#define CLTCTX_FUNC(ctx) (((ctx) >> 4) & 0xF) +#define CLTCTX_BLK_SZ(ctx) (((ctx) >> 0) & 0xFF00) +#define CLTCTX_IDX(ctx) ((ctx) & 0xF) +#define CLTCTX_IDX_VALID(idx) ((idx >= 0) && (idx < CFG_CLIENT_COUNT)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if HIF_SDIO_SUPPORT_SUSPEND +static int hif_sdio_suspend ( + struct device *dev + ); + +static int hif_sdio_resume ( + struct device *dev + ); +#endif +static int hif_sdio_probe ( + struct sdio_func *func, + const struct sdio_device_id *id + ); + +static void hif_sdio_remove ( + struct sdio_func *func + ); + +static void hif_sdio_irq ( + struct sdio_func *func + ); + +static int hif_sdio_clt_probe_func ( + MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, + INT8 probe_idx + ); + +static void hif_sdio_clt_probe_worker( + struct work_struct *work + ); + +static int hif_sdio_find_probed_list_index_by_func( + struct sdio_func *func + ); + +#if 0 // TODO:[ChangeFeature][George] remove obsolete function? +static int hif_sdio_find_probed_list_index_by_clt_index( + INT32 clt_index + ); +#endif + +static int hif_sdio_find_probed_list_index_by_id_func( + UINT16 vendor, + UINT16 device, + UINT16 func_num + ); + +static void hif_sdio_init_clt_list( + INT32 index + ); + +static int hif_sdio_find_clt_list_index ( + UINT16 vendor, + UINT16 device, + UINT16 func_num + ); + +static int hif_sdio_check_supported_sdio_id( + UINT16 vendor, + UINT16 device + ); + +static int hif_sdio_check_duplicate_sdio_id( + UINT16 vendor, + UINT16 device, + UINT16 func_num + ); + +static int hif_sdio_add_clt_list( + INT32* clt_index_p, + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, + UINT32 tbl_index + ); + +static INT32 hif_sdio_stp_on( + void + ); + +static INT32 hif_sdio_stp_off( + void + ); + +static INT32 hif_sdio_wifi_on( + void + ); + +static INT32 hif_sdio_wifi_off( + void + ); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* Supported SDIO device table */ +static const struct sdio_device_id mtk_sdio_id_tbl[] = { + /* MT6618 */ /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037A, 0x018A) }, /* SDIO1:WIFI */ + { SDIO_DEVICE(0x037A, 0x018B) }, /* SDIO2:FUNC1:BT+FM */ + { SDIO_DEVICE(0x037A, 0x018C) }, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */ + + /* MT6619 */ /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037A, 0x6619) }, /* SDIO2:FUNC1:BT+FM+GPS */ + + /* MT6620 */ /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037A, 0x020A) }, /* SDIO1:FUNC1:WIFI */ + { SDIO_DEVICE(0x037A, 0x020B) }, /* SDIO2:FUNC1:BT+FM+GPS */ + { SDIO_DEVICE(0x037A, 0x020C) }, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT5921 */ /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037A, 0x5921) }, + + /* MT6628 */ /* SDIO1: Wi-Fi, SDIO2: BGF */ + { SDIO_DEVICE(0x037A, 0x6628) }, + { /* end: all zeroes */ }, +}; + +#if HIF_SDIO_SUPPORT_SUSPEND +static const struct dev_pm_ops mtk_sdio_pmops = { + .suspend = hif_sdio_suspend, + .resume = hif_sdio_resume, +}; +#endif + +static struct sdio_driver mtk_sdio_client_drv = { + .name = "mtk_sdio_client", /* MTK SDIO Client Driver */ + .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */ + .probe = hif_sdio_probe, + .remove = hif_sdio_remove, +#if HIF_SDIO_SUPPORT_SUSPEND + .drv = { + .pm = &mtk_sdio_pmops, + }, +#endif +}; + +/* Registered client driver list */ +/* static list g_hif_sdio_clt_drv_list */ +static MTK_WCN_HIF_SDIO_REGISTINFO g_hif_sdio_clt_drv_list[CFG_CLIENT_COUNT]; + +/* MMC probed function list */ +/* static list g_hif_sdio_probed_func_list */ +static MTK_WCN_HIF_SDIO_PROBEINFO g_hif_sdio_probed_func_list[CFG_CLIENT_COUNT]; + +/* spin lock info for g_hif_sdio_clt_drv_list and g_hif_sdio_probed_func_list */ +static MTK_WCN_HIF_SDIO_LOCKINFO g_hif_sdio_lock_info; + +/* reference count, debug information? */ +static int gRefCount; +static int (*fp_wmt_tra_sdio_update)(void) = NULL; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3"); +MODULE_DESCRIPTION("MediaTek MT6620 HIF SDIO Driver"); + +MODULE_DEVICE_TABLE(sdio, mtk_sdio_id_tbl); + +UINT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if (WMT_PLAT_APEX==0) +extern int mtk_wcn_sdio_irq_flag_set (int falg); +#else +int mtk_wcn_sdio_irq_flag_set (int falg) +{ + return 0; +} +#endif + + + +/*! + * \brief register the callback funciton for record the timestamp of sdio access + * + * \param callback function + * + * \retval -EINVAL, when registered callback is invalid + * \retval 0, when registered callback is valid + */ +extern INT32 mtk_wcn_hif_sdio_update_cb_reg(int (*ts_update)(void)) +{ + if(ts_update){ + fp_wmt_tra_sdio_update = ts_update; + return 0; + } + else { + return -EINVAL; + } +} + + +/*! + * \brief update the accessing time of SDIO via callback function + * + * \param void + * + * \retval -EINVAL, when callback is not registered + * \retval returned value of callback + */ +static INT32 wmt_tra_sdio_update(VOID) +{ + if(fp_wmt_tra_sdio_update){ + return (*fp_wmt_tra_sdio_update)(); + } + else { + //HIF_SDIO_WARN_FUNC("wmt_tra_sdio_update == NULL\n"); + return -EINVAL; + } +} +/*! + * \brief Translate CLTCTX into a pointer to struct sdio_func if it is valid + * + * Translate a CLTCTX into a pointer to struct sdio_func if it is + * 1) probed by mmc_core, and + * 2) client driver is registered, and + * 3) clt_idx of client driver is valid + * + * \param ctx a context provided by client driver + * + * \retval null if any condition is not valie + * \retval a pointer to a struct sdio_func mapped by provided ctx + */ +static inline struct sdio_func* hif_sdio_ctx_to_func ( + MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ + UINT32 probe_index; + + //4 <1> check if ctx is valid, registered, and probed + probe_index = CLTCTX_IDX(ctx); + if (unlikely(!CLTCTX_IDX_VALID(probe_index))) /* invalid index in CLTCTX */ + { + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + return NULL; + } + else + { + if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0)) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client idx in probed list!ctx(0x%x) prob_idx(%d) clt_idx(%d)\n", + ctx, probe_index, g_hif_sdio_probed_func_list[probe_index].clt_idx); + return NULL; + } + } + return g_hif_sdio_probed_func_list[probe_index].func; +} + +/*! + * \brief MTK hif sdio client registration function + * + * Client uses this function to register itself to hif_sdio driver + * + * \param pinfo a pointer of client's information + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_client_reg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ) +{ + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 clt_index = -1; + UINT32 i = 0; + UINT32 j = 0; + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> check input pointer is valid + HIF_SDIO_ASSERT( pinfo ); + + //4 <2> check if input parameters are all supported and valid + for ( i=0; ifunc_tbl_size; i++ ) + { + ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id ); + if(ret) + { + HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n", + pinfo->func_tbl[i].manf_id, + pinfo->func_tbl[i].card_id); + goto out; + } + } + HIF_SDIO_DBG_FUNC("hif_sdio_check_supported_sdio_id() done!\n"); + + //4 <3> check if the specific {manf id, card id, function number} tuple is + //4 already resigstered + for ( i=0; ifunc_tbl_size; i++ ) + { + ret = hif_sdio_check_duplicate_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num ); + if(ret) + { + HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) of sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n", + pinfo->func_tbl[i].manf_id, + pinfo->func_tbl[i].card_id, + pinfo->func_tbl[i].func_num ); + goto out; + } + } + HIF_SDIO_DBG_FUNC("hif_sdio_check_duplicate_sdio_id() done!\n"); + + //4 <4> add the specified {manf id, card id, function number} tuple to registered client list + HIF_SDIO_DBG_FUNC("pinfo->func_tbl_size:%d\n", pinfo->func_tbl_size); + for ( i=0; ifunc_tbl_size; i++ ) + { + ret = hif_sdio_add_clt_list( &clt_index, pinfo, i ); + if(ret) + { + HIF_SDIO_WARN_FUNC("client's info are added in registed client list failed (buffer is full)!\n"); + goto out; + } + HIF_SDIO_DBG_FUNC("hif_sdio_add_clt_list() done (gRefCount=%d)!\n", gRefCount); + + //4 <5> if the specific {manf id, card id, function number} tuple has already + //4 been probed by mmc, schedule another task to call client's .hif_clt_probe() + for ( j=0; jmanf_id == g_hif_sdio_probed_func_list[j].func->vendor) &&\ + (g_hif_sdio_clt_drv_list[clt_index].func_info->card_id == g_hif_sdio_probed_func_list[j].func->device) &&\ + (g_hif_sdio_clt_drv_list[clt_index].func_info->func_num == g_hif_sdio_probed_func_list[j].func->num) ) + { + g_hif_sdio_probed_func_list[j].clt_idx = clt_index; + // probed spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + + /* use worker thread to perform the client's .hif_clt_probe() */ + clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) ); + INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker ); + clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index]; + clt_probe_worker_info->probe_idx = j; + schedule_work( &clt_probe_worker_info->probe_work ); + + //4 <5.1> remember to do claim_irq for the func if it's irq had been released. + if ( !(g_hif_sdio_probed_func_list[j].func->irq_handler) ) + { + sdio_claim_host(g_hif_sdio_probed_func_list[j].func); + ret = sdio_claim_irq(g_hif_sdio_probed_func_list[j].func, hif_sdio_irq); + mtk_wcn_sdio_irq_flag_set (1); + sdio_release_host(g_hif_sdio_probed_func_list[j].func); + HIF_SDIO_INFO_FUNC("sdio_claim_irq for func(0x%p) j(%d) v(0x%x) d(0x%x) ok\n", + g_hif_sdio_probed_func_list[j].func, j, + g_hif_sdio_probed_func_list[j].func->vendor, + g_hif_sdio_probed_func_list[j].func->device + ); + } + //4 <5.2> Reset the block size of the function provided by client + HIF_SDIO_INFO_FUNC("Reset sdio block size: %d!\n", g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz); + sdio_claim_host(g_hif_sdio_probed_func_list[j].func); + ret = sdio_set_block_size(g_hif_sdio_probed_func_list[j].func,\ + g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz); + sdio_release_host(g_hif_sdio_probed_func_list[j].func); + } + else + { + // probed spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + } + } + HIF_SDIO_DBG_FUNC("map g_hif_sdio_clt_drv_list to g_hif_sdio_probed_func_list done!\n"); + } + ret = HIF_SDIO_ERR_SUCCESS; + gRefCount++; + +out: + //4 error handling + + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_reg() */ + +/*! + * \brief MTK hif sdio client un-registration function + * + * Client uses this function to un-register itself + * + * \param pinfo a pointer of client's information + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_client_unreg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ) +{ + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 clt_list_index = 0; + UINT32 i = 0; + UINT32 j = 0; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> check if input pointer is valid + HIF_SDIO_ASSERT( pinfo ); + + //4 <2> check if input parameters are all supported and valid + for ( i=0; ifunc_tbl_size; i++ ) + { + ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id ); + if(ret) + { + HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n", + pinfo->func_tbl[i].manf_id, + pinfo->func_tbl[i].card_id); + goto out; + } + } + + //4 <3> check if the specific {manf id, card id, function number} tuple is already resigstered + //4 and find the corresponding client ctx and call client's .hif_clt_remove() in THIS context + for ( i=0; ifunc_tbl_size; i++ ) + { + clt_list_index = hif_sdio_find_clt_list_index(pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num); + if ( clt_list_index < 0 ) + { + HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) client info is not in the client's registed list!\n", + pinfo->func_tbl[i].manf_id, + pinfo->func_tbl[i].card_id, + pinfo->func_tbl[i].func_num ); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + + //4 <4> mark the specified {manf id, card id, function number} tuple as + //4 un-registered and invalidate client's context + hif_sdio_init_clt_list( clt_list_index ); + + /* un-map g_hif_sdio_clt_drv_list index in g_hif_sdio_probed_func_list */ + for ( j=0; j check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + + //4 <2> + sdio_claim_host(func); + *pvb = sdio_readb(func, offset, &ret); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_unreg() */ + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_writeb ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT8 vb + ) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func* func; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + int probe_index = -1; + struct sdio_func* func = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + + //4 <1> check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + + //4 <1.1> check if input parameters are valid + + //4 <2> + wmt_tra_sdio_update(); + sdio_claim_host(func); + sdio_writeb(func, vb, offset, &ret); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_unreg() */ + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_readl ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pvl + ) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func* func; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + int probe_index = -1; + struct sdio_func* func = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + HIF_SDIO_ASSERT( pvl ); + + //4 <1> check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + //4 <1.1> check if input parameters are valid + + //4 <2> + sdio_claim_host(func); + *pvl = sdio_readl(func, offset, &ret); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_unreg() */ + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_writel ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT32 vl + ) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func* func; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + int probe_index = -1; + struct sdio_func* func = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + + //4 <1> check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + //4 <1.1> check if input parameters are valid + + //4 <2> + wmt_tra_sdio_update(); + sdio_claim_host(func); + sdio_writel(func, vl, offset, &ret); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_unreg() */ + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_read_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func* func; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + int probe_index = -1; + struct sdio_func* func = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + HIF_SDIO_ASSERT( pbuf ); + + //4 <1> check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + //4 <1.1> check if input parameters are valid + + //4 <2> + sdio_claim_host(func); + ret = sdio_readsb(func, pbuf, offset, len); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_read_buf() */ + + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_write_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func* func; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + int probe_index = -1; + struct sdio_func* func = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + HIF_SDIO_ASSERT( pbuf ); + + //4 <1> check if ctx is valid, registered, and probed +#if HIF_SDIO_UPDATE + ret = -HIF_SDIO_ERR_FAIL; + func = hif_sdio_ctx_to_func(ctx); + if (!func) { + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } +#else + probe_index = CLTCTX_IDX(ctx); + if( probe_index < 0 ) /* the function has not been probed */ + { + HIF_SDIO_WARN_FUNC("can't find client in probed list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + else + { + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */ + { + HIF_SDIO_WARN_FUNC("can't find client in registered list!\n"); + ret = -HIF_SDIO_ERR_FAIL; + goto out; + } + } + func = g_hif_sdio_probed_func_list[probe_index].func; +#endif + //4 <1.1> check if input parameters are valid + + //4 <2> + wmt_tra_sdio_update(); + sdio_claim_host(func); + ret = sdio_writesb(func, offset, pbuf, len); + sdio_release_host(func); + + //4 <3> check result code and return proper error code + +out: + HIF_SDIO_DBG_FUNC("ret(%d) end!\n", ret); + + return ret; +} /* end of mtk_wcn_hif_sdio_write_buf() */ + +/*! + * \brief store client driver's private data function. + * + * + * \param clent's MTK_WCN_HIF_SDIO_CLTCTX. + * + * \retval none. + */ +void mtk_wcn_hif_sdio_set_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + void* private_data_p + ) +{ + UINT8 probed_idx = CLTCTX_IDX(ctx); + + if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), private_data_p not stored!\n", ctx); + } + else { + /* store client driver's private data to dev driver */ + g_hif_sdio_probed_func_list[probed_idx].private_data_p = private_data_p; + HIF_SDIO_DBG_FUNC("private_data_p(0x%p) for ctx(0x%x) probed idx(%d) stored!\n", + private_data_p, ctx, probed_idx); + } +} + +/*! + * \brief get client driver's private data function. + * + * + * \param clent's MTK_WCN_HIF_SDIO_CLTCTX. + * + * \retval private data pointer. + */ +void* mtk_wcn_hif_sdio_get_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx + ) +{ + UINT8 probed_idx = CLTCTX_IDX(ctx); + + /* get client driver's private data to dev driver */ + if (likely(CLTCTX_IDX_VALID(probed_idx))) + { + return g_hif_sdio_probed_func_list[probed_idx].private_data_p; + } + else + { + /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx); + return NULL; + } +} + +/*! + * \brief control stp/wifi on/off from wmt. + * + * + * \param (1)control function type, (2)on/off control. + * + * \retval (1)control results ,(2)unknow type: -5. + * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors. + */ +INT32 +mtk_wcn_hif_sdio_wmt_control ( + WMT_SDIO_FUNC_TYPE func_type, + MTK_WCN_BOOL is_on + ) +{ + // TODO:[FixMe][George]: return value of this function shall distinguish + // 1) not probed by mmc_core yet or + // 2) probed by mmc_core but init fail... + switch (func_type) { + case WMT_SDIO_FUNC_STP: + if (is_on == MTK_WCN_BOOL_TRUE) { + return hif_sdio_stp_on(); + } + else { + return hif_sdio_stp_off(); + } + break; + + case WMT_SDIO_FUNC_WIFI: + if (is_on == MTK_WCN_BOOL_TRUE) { + return hif_sdio_wifi_on(); + } + else { + return hif_sdio_wifi_off(); + } + break; + + default: + HIF_SDIO_WARN_FUNC("unknown type(%d)\n", func_type); + return HIF_SDIO_ERR_INVALID_PARAM; + } +} + +/*! + * \brief ??? + * + * \detail ??? + * + * \param ctx a context provided by client driver + * \param struct device ** ??? + * + * \retval none + */ +void mtk_wcn_hif_sdio_get_dev( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + struct device **dev + ) +{ +#if HIF_SDIO_UPDATE + struct sdio_func* func; +#else + UINT8 probe_index = CLTCTX_IDX(ctx); +#endif + +#if HIF_SDIO_UPDATE + *dev = NULL; //ensure we does not return any invalid value back. + func = hif_sdio_ctx_to_func(ctx); + if (unlikely(!func)) { + HIF_SDIO_WARN_FUNC("no valid *func with ctx(0x%x)\n", ctx); + return; + } + else { + *dev = &(func->dev); + HIF_SDIO_DBG_FUNC("return *dev(0x%p) for ctx(0x%x)\n", *dev, ctx); + } +#else + if (probe_index < 0) { + HIF_SDIO_WARN_FUNC("func not probed, probe_index = %d", probe_index); + return; + } + else{ + *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev; + } +#endif +} + +/*! + * \brief client's probe() function. + * + * + * \param work queue structure. + * + * \retval none. + */ +static int hif_sdio_clt_probe_func ( + MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, + INT8 probe_idx + ) +{ + UINT16 card_id = 0; + UINT16 func_num = 0; + UINT16 blk_sz = 0; + int ret; + + HIF_SDIO_DBG_FUNC("start!\n"); + HIF_SDIO_ASSERT( registinfo_p ); + if (!registinfo_p) { + HIF_SDIO_WARN_FUNC("registinfo_p NULL!!!\n"); + return -1; + } + + /* special case handling: if the clt's unregister is called during probe procedures */ + if ( !registinfo_p->func_info || !registinfo_p->sdio_cltinfo) { + HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n"); + return -1; + } + + card_id = registinfo_p->func_info->card_id; + func_num = registinfo_p->func_info->func_num; + blk_sz = registinfo_p->func_info->blk_sz; + ret = registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, probe_idx),\ + registinfo_p->func_info ); + + HIF_SDIO_INFO_FUNC("clt_probe_func card_id(%x) func_num(%x) blk_sz(%d) prob_idx(%x) ret(%d) %s\n", + card_id, func_num, blk_sz, probe_idx, ret, (ret) ? "fail" : "ok"); + + return ret; +} + +/*! + * \brief client's probe() worker. + * + * + * \param work queue structure. + * + * \retval none. + */ +static void hif_sdio_clt_probe_worker( + struct work_struct *work + ) +{ + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_worker_info_p = 0; + UINT16 card_id = 0; + UINT16 func_num = 0; + UINT16 blk_sz = 0; + INT8 prob_idx = 0; + + HIF_SDIO_DBG_FUNC("start!\n"); + + HIF_SDIO_ASSERT( work ); + + /* get client's information */ + clt_worker_info_p = container_of( work, MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO, probe_work ); + HIF_SDIO_ASSERT( clt_worker_info_p ); + HIF_SDIO_ASSERT( clt_worker_info_p->registinfo_p ); + + /* special case handling: if the clt's unregister is called during probe procedures */ + if ( (clt_worker_info_p->registinfo_p->func_info == 0) || (clt_worker_info_p->registinfo_p->sdio_cltinfo==0) ) + { + HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n"); + vfree( clt_worker_info_p ); + return; + } + + card_id = clt_worker_info_p->registinfo_p->func_info->card_id; + func_num = clt_worker_info_p->registinfo_p->func_info->func_num; + blk_sz = clt_worker_info_p->registinfo_p->func_info->blk_sz; + prob_idx = clt_worker_info_p->probe_idx; + + /* Execute client's probe() func */ + clt_worker_info_p->registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, prob_idx),\ + clt_worker_info_p->registinfo_p->func_info ); + + vfree( clt_worker_info_p ); + + HIF_SDIO_DBG_FUNC("card_id(0x%x) func_num(0x%x) blk_sz(0x%x) prob_idx(0x%x)\n", card_id, func_num, blk_sz, prob_idx); + HIF_SDIO_DBG_FUNC("end!\n"); +} + +/*! + * \brief client's probe() worker. + * + * + * \param work queue structure. + * + * \retval none. + */ +static void +hif_sdio_dump_probe_list (void) +{ + int i; + + HIF_SDIO_DBG_FUNC("== DUMP probed list start ==\n"); + + for (i = 0; i < CFG_CLIENT_COUNT; i++) { + if (g_hif_sdio_probed_func_list[i].func) { + HIF_SDIO_DBG_FUNC("index(%d) func(0x%p) clt_idx(%d)\n", + i, g_hif_sdio_probed_func_list[i].func, + g_hif_sdio_probed_func_list[i].clt_idx); + + HIF_SDIO_DBG_FUNC("vendor(0x%x) device(0x%x) num(0x%x) state(%d)\n", + g_hif_sdio_probed_func_list[i].func->vendor, + g_hif_sdio_probed_func_list[i].func->device, + g_hif_sdio_probed_func_list[i].func->num, + g_hif_sdio_probed_func_list[i].on_by_wmt); + + } + } + + HIF_SDIO_DBG_FUNC("== DUMP probed list end ==\n"); +} + + +/*! + * \brief Initialize g_hif_sdio_probed_func_list + * + * + * \param index of g_hif_sdio_probed_func_list. + * + * \retval none. + */ +static void hif_sdio_init_probed_list( + INT32 index + ) +{ + if ( (index >= 0) && (index < CFG_CLIENT_COUNT) ) + { + /* probed spin lock */ + spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + g_hif_sdio_probed_func_list[index].func = 0; + g_hif_sdio_probed_func_list[index].clt_idx = -1; + g_hif_sdio_probed_func_list[index].private_data_p = 0; + g_hif_sdio_probed_func_list[index].on_by_wmt = MTK_WCN_BOOL_FALSE; + /* probed spin unlock */ + spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + } + else + { + HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_probed_func_list[] boundary!\n"); + } +} + + +/*! + * \brief Initialize g_hif_sdio_clt_drv_list + * + * + * \param index of g_hif_sdio_clt_drv_list. + * + * \retval none. + */ +static void hif_sdio_init_clt_list( + INT32 index + ) +{ + // client list spin lock + spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock ); + if ( (index >= 0) && (index < CFG_CLIENT_COUNT) ) + { + g_hif_sdio_clt_drv_list[index].sdio_cltinfo = 0; + g_hif_sdio_clt_drv_list[index].func_info = 0; + } + else + { + HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_clt_drv_list[] boundary!\n"); + } + // client list spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock ); +} + + +/*! + * \brief find matched g_hif_sdio_probed_func_list index from sdio function handler + * + * + * \param sdio function handler + * + * \retval -1 index not found + * \retval >= 0 return found index + */ +static int hif_sdio_find_probed_list_index_by_func( + struct sdio_func* func + ) +{ + int i = 0; + + HIF_SDIO_ASSERT( func ); + + for( i=0; i= 0 return found index + */ +static int hif_sdio_find_probed_list_index_by_id_func( + UINT16 vendor, + UINT16 device, + UINT16 func_num + ) +{ + int i; + for (i = 0; i < CFG_CLIENT_COUNT; i++) { + if (g_hif_sdio_probed_func_list[i].func) { + HIF_SDIO_DBG_FUNC("probed entry: vendor(0x%x) device(0x%x) num(0x%x)\n", + g_hif_sdio_probed_func_list[i].func->vendor, + g_hif_sdio_probed_func_list[i].func->device, + g_hif_sdio_probed_func_list[i].func->num); + } + } + for (i = 0; i < CFG_CLIENT_COUNT; i++) { + if (!g_hif_sdio_probed_func_list[i].func) { + continue; + } + else if ( (g_hif_sdio_probed_func_list[i].func->vendor == vendor) && + (g_hif_sdio_probed_func_list[i].func->device == device) && + (g_hif_sdio_probed_func_list[i].func->num == func_num) ) + { + return i; + } + } + + if (i == CFG_CLIENT_COUNT ) { + /* + printk(KERN_INFO DRV_NAME "Cannot find vendor:0x%x, device:0x%x, func_num:0x%x, i=%d\n", + vendor, device, func_num, i); + */ + /* client func has not been probed */ + return -1; + } + return -1; +} + +/*! + * \brief find matched g_hif_sdio_clt_drv_list index + * + * find the matched g_hif_sdio_clt_drv_list index from card_id and function number. + * + * \param vendor id, device id, and function number of the sdio card + * + * \retval -1 index not found + * \retval >= 0 return found index + */ +static int hif_sdio_find_clt_list_index ( + UINT16 vendor, + UINT16 device, + UINT16 func_num + ) +{ + int i = 0; + + for( i=0; imanf_id == vendor ) &&\ + (g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\ + (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) ) + { + return i; + } + } + } + + return -1; +} + + +/*! + * \brief check if the vendor, device ids are supported in mtk_sdio_id_tbl. + * + * + * \param vendor id and device id of the sdio card + * + * \retval (-HIF_SDIO_ERR_FAIL) vendor, device ids are not suppported + * \retval HIF_SDIO_ERR_SUCCESS vendor, device ids are suppported + */ +static int hif_sdio_check_supported_sdio_id( + UINT16 vendor, + UINT16 device + ) +{ + int i = 0; + + for ( i=0; imanf_id == vendor ) &&\ + ( g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\ + ( g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) ) + { + return (-HIF_SDIO_ERR_DUPLICATED); /* duplicated */ + } + } + } + return HIF_SDIO_ERR_SUCCESS; /* Not duplicated */ +} + + +/*! + * \brief Add the client info into g_hif_sdio_clt_drv_list. + * + * + * \param [output] client's index pointer. + * \param MTK_WCN_HIF_SDIO_CLTINFO of client's contex. + * + * \retval (-HIF_SDIO_ERR_FAIL) Add to clt_list successfully + * \retval HIF_SDIO_ERR_SUCCESS Add to clt_list failed (buffer is full) + */ +static int hif_sdio_add_clt_list( + INT32* clt_index_p, + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, + UINT32 tbl_index + ) +{ + int i = 0; + + HIF_SDIO_ASSERT( clt_index_p ); + HIF_SDIO_ASSERT( pinfo ); + + for( i=0; ifunc_tbl[tbl_index]); + g_hif_sdio_clt_drv_list[i].sdio_cltinfo = pinfo; + // client list spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock ); + *clt_index_p = i; + return HIF_SDIO_ERR_SUCCESS; /* Add to client list successfully */ + } + // client list spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock ); + } + return (-HIF_SDIO_ERR_FAIL); /* Add to client list failed (buffer is full) */ +} + +#if HIF_SDIO_SUPPORT_SUSPEND +static int hif_sdio_suspend (struct device *dev) +{ + struct sdio_func* func; + mmc_pm_flag_t flag; + int ret; + + if (!dev) { + return -EINVAL; + } + + func = dev_to_sdio_func(dev); + HIF_SDIO_DBG_FUNC("prepare for func(0x%p)\n", func); + + flag = sdio_get_host_pm_caps(func); + if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) { + HIF_SDIO_WARN_FUNC("neither MMC_PM_KEEP_POWER nor MMC_PM_WAKE_SDIO_IRQ is supported by host, return -ENOTSUPP\n"); + return -ENOTSUPP; + } + + /* set both */ + flag = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; + ret = sdio_set_host_pm_flags(func, flag); + if (ret) { + HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ to host fail(%d)\n", ret); + return -EFAULT; + } + sdio_claim_host(func); + HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ ok\n"); + return 0; +} + +static int hif_sdio_resume (struct device *dev) +{ + struct sdio_func* func; + + if (!dev) { + HIF_SDIO_WARN_FUNC("null dev!\n"); + return -EINVAL; + } + func = dev_to_sdio_func(dev); + sdio_release_host(func); + HIF_SDIO_DBG_FUNC("do nothing for func(0x%p)\n", func); + + return 0; +} +#endif + +/*! + * \brief hif_sdio probe function + * + * hif_sdio probe function called by mmc driver when any matched SDIO function + * is detected by it. + * + * \param func + * \param id + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +static int hif_sdio_probe ( + struct sdio_func *func, + const struct sdio_device_id *id + ) +{ + int ret = 0; + int i = 0; + MTK_WCN_HIF_SDIO_PROBEINFO* hif_sdio_probed_funcp = 0; + INT32 probe_index = -1; +#if 0 + INT32 clt_index = -1; + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0; +#endif + + HIF_SDIO_INFO_FUNC("start!\n"); + HIF_SDIO_ASSERT( func ); + hif_sdio_match_chipid_by_dev_id(id); + //4 <0> display debug information + HIF_SDIO_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num); + for (i = 0;i < func->card->num_info;i++) { + HIF_SDIO_INFO_FUNC("card->info[%d]: %s\n", i, func->card->info[i]); + } + + //4 <1> Check if this is supported by us (mtk_sdio_id_tbl) + ret = hif_sdio_check_supported_sdio_id( func->vendor, func->device ); + if (ret) { + HIF_SDIO_WARN_FUNC("vendor id and device id of sdio_func are not supported in mtk_sdio_id_tbl!\n"); + goto out; + } + + //4 <2> Add this struct sdio_func *func to g_hif_sdio_probed_func_list + for( i=0; ifunc = func; + hif_sdio_probed_funcp->clt_idx = hif_sdio_find_clt_list_index(func->vendor, func->device, func->num); + hif_sdio_probed_funcp->on_by_wmt = MTK_WCN_BOOL_FALSE; + hif_sdio_probed_funcp->sdio_irq_enabled = MTK_WCN_BOOL_FALSE; + /* probed spin unlock */ + spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + probe_index = i; + break; + } + else + { + /* probed spin unlock */ + spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock ); + } + } + if ( (probe_index < 0) || (probe_index >= CFG_CLIENT_COUNT) ) + { + HIF_SDIO_ERR_FUNC("probe function list if full!\n"); + goto out; + } + + //4 <3> Initialize this function + if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) + { + for( i=0; imanf_id, g_hif_sdio_clt_drv_list[i].func_info->card_id, g_hif_sdio_clt_drv_list[i].func_info->func_num ); + if ( (g_hif_sdio_clt_drv_list[i].func_info->manf_id == g_hif_sdio_probed_func_list[probe_index].func->vendor)&&\ + (g_hif_sdio_clt_drv_list[i].func_info->card_id == g_hif_sdio_probed_func_list[probe_index].func->device)&&\ + (g_hif_sdio_clt_drv_list[i].func_info->func_num == g_hif_sdio_probed_func_list[probe_index].func->num) ) + { + g_hif_sdio_probed_func_list[probe_index].clt_idx = i; + // client list spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock ); + break; + } + else + { + // client list spin unlock + spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock ); + } + } + HIF_SDIO_INFO_FUNC("map to g_hif_sdio_clt_drv_list[] done: %d\n", g_hif_sdio_probed_func_list[probe_index].clt_idx ); + } + + //4 <3.1> enable this function + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + if (ret) { + HIF_SDIO_ERR_FUNC("sdio_enable_func failed!\n"); + goto out; + } + + //4 <3.2> set block size according to the table storing function characteristics + if ( hif_sdio_probed_funcp == 0 ) + { + HIF_SDIO_ERR_FUNC("hif_sdio_probed_funcp is null!\n"); + goto out; + } + if ( hif_sdio_probed_funcp->clt_idx >= 0 ) /* The clt contex has been registed */ + { + sdio_claim_host(func); + ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[hif_sdio_probed_funcp->clt_idx].func_info->blk_sz); + sdio_release_host(func); + } + else /* The clt contex has not been registed */ + { + sdio_claim_host(func); + ret = sdio_set_block_size(func, HIF_DEFAULT_BLK_SIZE); + sdio_release_host(func); + } + if (ret) { + HIF_SDIO_ERR_FUNC("set sdio block size failed!\n"); + goto out; + } + + HIF_SDIO_INFO_FUNC("cur_blksize(%d) max(%d), host max blk_size(%d) blk_count(%d)\n", + func->cur_blksize, func->max_blksize, + func->card->host->max_blk_size, func->card->host->max_blk_count + ); + + // TODO:[ChangeFeature][George]: explain why this block is marked +#if 0 + //4 <3.3> claim irq for this function + sdio_claim_host(func); + ret = sdio_claim_irq(func, hif_sdio_irq); + sdio_release_host(func); + printk(KERN_INFO "sdio_claim_irq ret=%d\n", ret); + + //4 <3.4> If this struct sdio_func *func is supported by any driver in + //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() + if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */ + { + /* use worker thread to perform the client's .hif_clt_probe() */ + clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) ); + INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker ); + clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index]; + clt_probe_worker_info->probe_idx = probe_index; + schedule_work( &clt_probe_worker_info->probe_work ); + } +#endif + + hif_sdio_dump_probe_list(); + +out: + //4 error handling + return ret; +} + + +/*! + * \brief hif_sdio remove function + * + * hif_sdio probe function called by mmc driver when the probed func should be + * removed. + * + * \param func + * + */ +static void hif_sdio_remove ( + struct sdio_func *func + ) +{ + int probed_list_index = 0; +#if 0 + int registed_list_index = 0; +#endif + + HIF_SDIO_INFO_FUNC("start!\n"); + HIF_SDIO_ASSERT( func ); + + //4 <1> check input parameter is valid and has been probed previously + if (func == NULL) { + HIF_SDIO_ERR_FUNC("func null(%p)\n", func); + return; + } + + //4 <2> if this function has been initialized by any client driver, + //4 call client's .hif_clt_remove() call back in THIS context. + probed_list_index = hif_sdio_find_probed_list_index_by_func( func ); + if ( probed_list_index < 0 ) + { + HIF_SDIO_WARN_FUNC("sdio function pointer is not in g_hif_sdio_probed_func_list!\n"); + return; + } +#if 0 + registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx; + if ( registed_list_index >= 0 ) + { + g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_remove( CLTCTX(func->device, func->num,\ + func->cur_blksize, probed_list_index) ); + } +#endif + + //4 <3> mark this function as de-initialized and invalidate client's context + hif_sdio_init_probed_list(probed_list_index); + +#if 0 + //4 <4> release irq for this function + sdio_claim_host(func); + sdio_release_irq(func); + sdio_release_host(func); +#endif + + //4 <5> disable this function + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + //4 <6> mark this function as removed + + HIF_SDIO_INFO_FUNC("sdio func(0x%p) is removed successfully!\n", func); +} + +/*! + * \brief hif_sdio interrupt handler + * + * detailed descriptions + * + * \param ctx client's context variable + * + */ +static void hif_sdio_irq ( + struct sdio_func *func + ) +{ + int probed_list_index = -1; + int registed_list_index = -1; + + HIF_SDIO_DBG_FUNC("start!\n"); + + //4 <1> check if func is valid + HIF_SDIO_ASSERT( func ); + + //4 <2> if func has valid corresponding hif_sdio client's context, mark it + //4 host-locked, use it to call client's .hif_clt_irq() callback function in + //4 THIS context. + probed_list_index = hif_sdio_find_probed_list_index_by_func( func ); + if ( (probed_list_index < 0) || (probed_list_index >= CFG_CLIENT_COUNT) ) + { + HIF_SDIO_ERR_FUNC("probed_list_index not found!\n"); + return; + } + /* [George] added for sdio irq sync and mmc single_irq workaround. It's set + * enabled later by client driver call mtk_wcn_hif_sdio_enable_irq() + */ + /* skip smp_rmb() here */ + if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled) { + HIF_SDIO_WARN_FUNC("func(0x%p),probed_idx(%d) sdio irq not enabled yet\n", + func, probed_list_index); + return; + } + + registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx; +// g_hif_sdio_probed_func_list[probed_list_index].interrupted = MTK_WCN_BOOL_TRUE; + if ( (registed_list_index >= 0) + && (registed_list_index < CFG_CLIENT_COUNT) ) { + g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_irq( CLTCTX(func->device,\ + func->num, func->cur_blksize, probed_list_index) ); + } + else { + //4 <3> if func has no VALID hif_sdio client's context, release irq for this + //4 func and mark it in g_hif_sdio_probed_func_list (remember: donnot claim host in irq contex). + HIF_SDIO_WARN_FUNC("release irq (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n", + func, func->vendor, func->device, func->num); + mtk_wcn_sdio_irq_flag_set (0); + sdio_release_irq(func); + } + + return; +} + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static int __init hif_sdio_init(void) +{ + int ret = 0; + INT32 i = 0; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> init all private variables + /* init reference count to 0 */ + gRefCount = 0; + + /* init spin lock information */ + spin_lock_init( &g_hif_sdio_lock_info.probed_list_lock ); + spin_lock_init( &g_hif_sdio_lock_info.clt_list_lock ); + + /* init probed function list and g_hif_sdio_clt_drv_list */ + for ( i=0; i register to mmc driver + ret = sdio_register_driver(&mtk_sdio_client_drv); + HIF_SDIO_INFO_FUNC("sdio_register_driver() ret=%d\n", ret); + + //4 <3> create thread for query chip id and device node for launcher to access + if (0 == hifsdiod_start()) + { + hif_sdio_create_dev_node(); + } + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static VOID __exit hif_sdio_exit(void) +{ + HIF_SDIO_INFO_FUNC("start!\n"); + + hif_sdio_remove_dev_node(); + + hifsdiod_stop(); + //4 <0> if client driver is not removed yet, we shall NOT be called... + + //4 <1> check reference count + if ( gRefCount !=0 ) + { + HIF_SDIO_WARN_FUNC("gRefCount=%d !!!\n", gRefCount); + } + + //4 <2> check if there is any hif_sdio-registered clients. There should be + //4 no registered client... + + //4 <3> Reregister with mmc driver. Our remove handler hif_sdio_remove() + //4 will be called later by mmc_core. Clean up driver resources there. + sdio_unregister_driver(&mtk_sdio_client_drv); + + HIF_SDIO_DBG_FUNC("end!\n"); + return; +} /* end of exitWlan() */ + +/*! + * \brief stp on by wmt (probe client driver). + * + * + * \param none. + * + * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors. + */ +INT32 hif_sdio_stp_on( + void + ) +{ +#if 0 + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0; +#endif + INT32 clt_index = -1; + INT32 probe_index = -1; + struct sdio_func *func = 0; + int ret = -1; + int ret2 = -1; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> If stp client drv has not been probed, return error code + /* MT6620 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 ) + { + goto stp_on_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 ) + { + goto stp_on_exist; + } + + /* MT6628 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 ) + { + goto stp_on_exist; + } + /* MT6619 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 ) + { + goto stp_on_exist; + } + + /* MT6618 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 ) + { + goto stp_on_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 ) + { + goto stp_on_exist; + } + else + { + //4 <2> If stp client drv has not been probed, return error code + /* client func has not been probed */ + HIF_SDIO_INFO_FUNC("no supported func probed \n"); + return HIF_SDIO_ERR_NOT_PROBED; + } + +stp_on_exist: + //4 <3> If stp client drv has been on by wmt, return error code + if (MTK_WCN_BOOL_FALSE != g_hif_sdio_probed_func_list[probe_index].on_by_wmt) { + HIF_SDIO_INFO_FUNC("already on...\n"); + return HIF_SDIO_ERR_ALRDY_ON; + } + else { + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE; + } + + if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */ + { + g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE; + //4 <4> claim irq for this function + func = g_hif_sdio_probed_func_list[probe_index].func; + sdio_claim_host(func); + ret = sdio_claim_irq(func, hif_sdio_irq); + mtk_wcn_sdio_irq_flag_set (1); + sdio_release_host(func); + if (ret) { + HIF_SDIO_WARN_FUNC("sdio_claim_irq() for stp fail(%d)\n", ret); + return ret; + } + HIF_SDIO_INFO_FUNC("sdio_claim_irq() for stp ok\n"); + + //4 <5> If this struct sdio_func *func is supported by any driver in + //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() + // TODO: [FixMe][George] WHY probe worker is removed??? +#if 1 + /* Call client's .hif_clt_probe() */ + ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index); + if (ret) { + HIF_SDIO_WARN_FUNC("clt_probe_func() for stp fail(%d) release irq\n", ret); + sdio_claim_host(func); + mtk_wcn_sdio_irq_flag_set (0); + ret2 = sdio_release_irq(func); + sdio_release_host(func); + if (ret2) { + HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2); + } + + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE; + return ret; + } + HIF_SDIO_INFO_FUNC("ok!\n"); + + return 0; +#else + /* use worker thread to perform the client's .hif_clt_probe() */ + clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) ); + INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker ); + clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index]; + clt_probe_worker_info->probe_idx = probe_index; + schedule_work( &clt_probe_worker_info->probe_work ); +#endif + } + else { + // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function + HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret); + return HIF_SDIO_ERR_CLT_NOT_REG; + } +} + +/*! + * \brief stp off by wmt (remove client driver). + * + * + * \param none. + * + * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors. + */ +INT32 hif_sdio_stp_off( + void + ) +{ + INT32 clt_index = -1; + INT32 probe_index = -1; + struct sdio_func *func = 0; + int ret = -1; + int ret2 = -1; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> If stp client drv has not been probed, return error code + /* MT6620 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 ) + { + goto stp_off_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 ) + { + goto stp_off_exist; + } + + /* MT6628 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 ) + { + goto stp_off_exist; + } + + /* MT6619 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 ) + { + goto stp_off_exist; + } + + /* MT6618 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 ) + { + goto stp_off_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 ) + { + goto stp_off_exist; + } + else + { + //4 <2> If stp client drv has not been probed, return error code + /* client func has not been probed */ + return HIF_SDIO_ERR_NOT_PROBED; + } + +stp_off_exist: + //4 <3> If stp client drv has been off by wmt, return error code + if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) { + HIF_SDIO_WARN_FUNC("already off...\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + else { + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE; + } + +#if 0 // TODO: [FixMe][George] moved below as done in stp_on. + //4 <4> release irq for this function + func = g_hif_sdio_probed_func_list[probe_index].func; + sdio_claim_host(func); + ret = sdio_release_irq(func); + sdio_release_host(func); + if (ret) { + printk(KERN_WARNING DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret); + } + else { + printk(KERN_INFO DRV_NAME "sdio_release_irq for stp ok\n"); + } +#endif + + if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */ + { + func = g_hif_sdio_probed_func_list[probe_index].func; + + //4 <4> Callback to client driver's remove() func + ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove( + CLTCTX(func->device, func->num, func->cur_blksize, probe_index) ); + if (ret) { + HIF_SDIO_WARN_FUNC("clt_remove for stp fail(%d)\n", ret); + } + else { + HIF_SDIO_INFO_FUNC("ok!\n"); + } + + //4 <5> release irq for this function + sdio_claim_host(func); + mtk_wcn_sdio_irq_flag_set (0); + ret2 = sdio_release_irq(func); + sdio_release_host(func); + + g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE; + if (ret2) { + HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2); + } + else { + HIF_SDIO_INFO_FUNC("sdio_release_irq() for stp ok\n"); + } + + return (ret + ret2); + } + else { + // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function + HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret); + return HIF_SDIO_ERR_CLT_NOT_REG; + } +} + +/*! + * \brief wifi on by wmt (probe client driver). + * + * + * \param none. + * + * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors. + */ +INT32 +hif_sdio_wifi_on (void) +{ +#if 0 + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0; +#endif + INT32 clt_index = -1; + INT32 probe_index = -1; + struct sdio_func *func = 0; + int ret = 0; + int ret2 = 0; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> If wifi client drv has not been probed, return error code + /* MT6620 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 ) + { + goto wifi_on_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 ) + { + goto wifi_on_exist; + } + /* MT6628 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 ) + { + goto wifi_on_exist; + } + /* MT6618 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 ) + { + goto wifi_on_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 ) + { + goto wifi_on_exist; + } + else + { + //4 <2> If wifi client drv has not been probed, return error code + /* client func has not been probed */ + return HIF_SDIO_ERR_NOT_PROBED; + } + +wifi_on_exist: + //4 <3> If wifi client drv has been on by wmt, return error code + if (g_hif_sdio_probed_func_list[probe_index].on_by_wmt) { + HIF_SDIO_INFO_FUNC("probe_index (%d), already on...\n", probe_index); + return HIF_SDIO_ERR_ALRDY_ON; + } + + if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */ + { + g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE; + //4 <4> claim irq for this function + func = g_hif_sdio_probed_func_list[probe_index].func; + sdio_claim_host(func); + ret = sdio_claim_irq(func, hif_sdio_irq); + mtk_wcn_sdio_irq_flag_set (1); + sdio_release_host(func); + if (ret) { + HIF_SDIO_WARN_FUNC("sdio_claim_irq() for wifi fail(%d)\n", ret); + return ret; + } + HIF_SDIO_INFO_FUNC("sdio_claim_irq() for wifi ok\n"); + + //4 <5> If this struct sdio_func *func is supported by any driver in + //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() + // TODO: [FixMe][George] WHY probe worker is removed??? +#if 1 + /* Call client's .hif_clt_probe() */ + ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index); + if (ret) { + HIF_SDIO_WARN_FUNC("clt_probe_func() for wifi fail(%d) release irq\n", ret); + sdio_claim_host(func); + mtk_wcn_sdio_irq_flag_set (0); + ret2 = sdio_release_irq(func); + sdio_release_host(func); + if (ret2) { + HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2); + } + + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE; + return ret; + } + else + { + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE; + } + HIF_SDIO_INFO_FUNC("ok!\n"); + return 0; +#else + /* use worker thread to perform the client's .hif_clt_probe() */ + clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) ); + INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker ); + clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index]; + clt_probe_worker_info->probe_idx = probe_index; + schedule_work( &clt_probe_worker_info->probe_work ); +#endif + } + else { + // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function + HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret); + return HIF_SDIO_ERR_CLT_NOT_REG; + } +} + +/*! + * \brief wifi off by wmt (remove client driver). + * + * + * \param none. + * + * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors. + */ +INT32 hif_sdio_wifi_off( + void + ) +{ + INT32 clt_index = -1; + INT32 probe_index = -1; + struct sdio_func *func = 0; + int ret = -1; + int ret2 = -1; + + HIF_SDIO_INFO_FUNC("start!\n"); + + //4 <1> If wifi client drv has not been probed, return error code + /* MT6620 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 ) + { + goto wifi_off_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 ) + { + goto wifi_off_exist; + } + + /* MT6628 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 ) + { + goto wifi_off_exist; + } + + /* MT6618 */ + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 ) + { + goto wifi_off_exist; + } + if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 ) + { + goto wifi_off_exist; + } + else + { + //4 <2> If wifi client drv has not been probed, return error code + /* client func has not been probed */ + return HIF_SDIO_ERR_NOT_PROBED; + } + +wifi_off_exist: + //4 <3> If wifi client drv has been off by wmt, return error code + if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) { + HIF_SDIO_WARN_FUNC("already off...\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + else { + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE; + } + +#if 0 // TODO: [FixMe][George] moved below as done in wifi_on. + //4 <4> release irq for this function + func = g_hif_sdio_probed_func_list[probe_index].func; + sdio_claim_host(func); + ret = sdio_release_irq(func); + sdio_release_host(func); + if (ret) { + printk(KERN_WARNING DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret); + } + else { + printk(KERN_INFO DRV_NAME "sdio_release_irq for wifi ok\n"); + } +#endif + + if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */ + { + func = g_hif_sdio_probed_func_list[probe_index].func; + + //4 <4> Callback to client driver's remove() func + ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove( + CLTCTX(func->device, func->num, func->cur_blksize, probe_index) ); + if (ret) { + HIF_SDIO_WARN_FUNC("clt_remove for wifi fail(%d)\n", ret); + } + else { + HIF_SDIO_INFO_FUNC("ok!\n"); + } + + //4 <5> release irq for this function + sdio_claim_host(func); + mtk_wcn_sdio_irq_flag_set (0); + ret2 = sdio_release_irq(func); + sdio_release_host(func); + g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE; + if (ret2) { + HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2); + } + else { + HIF_SDIO_INFO_FUNC("sdio_release_irq() for wifi ok\n"); + } + return (ret + ret2); + } + else { + // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function + HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret); + return HIF_SDIO_ERR_CLT_NOT_REG; + } +} + +/*! + * \brief set mmc power up/off + * + * detailed descriptions + * + * \param: 1. ctx client's context variable, 2.power state: 1:power up, other:power off + * + * \retval 0:success, -1:fail + */ +INT32 mtk_wcn_hif_sdio_bus_set_power ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 pwrState + ) +{ + int probe_index = -1; + struct sdio_func *func = 0; + + HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState); + + probe_index = CLTCTX_IDX(ctx); + func = g_hif_sdio_probed_func_list[probe_index].func; + + if ( !func ) + { + HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n"); + return -1; + } + + if ( 1 == pwrState ) + { + sdio_claim_host( func ); + mmc_power_up_ext( func->card->host ); + sdio_release_host( func ); + HIF_SDIO_WARN_FUNC("SDIO BUS Power UP\n"); + } + else + { + sdio_claim_host( func ); + mmc_power_off_ext( func->card->host ); + sdio_release_host( func ); + HIF_SDIO_WARN_FUNC("SDIO BUS Power OFF\n"); + } + + return 0; +} + +void mtk_wcn_hif_sdio_enable_irq( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + MTK_WCN_BOOL enable + ) +{ + UINT8 probed_idx = CLTCTX_IDX(ctx); + + if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx); + return; + } + + /* store client driver's private data to dev driver */ + g_hif_sdio_probed_func_list[probed_idx].sdio_irq_enabled = enable; + smp_wmb(); + HIF_SDIO_INFO_FUNC("ctx(0x%x) sdio irq enable(%d)\n", + ctx, (MTK_WCN_BOOL_FALSE == enable) ? 0 : 1); + + +} + +module_init(hif_sdio_init); +module_exit(hif_sdio_exit); + +EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_reg); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_unreg); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_read_buf); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_buf); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev); +EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq); + + diff --git a/drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c b/drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c new file mode 100755 index 000000000000..42123e64a835 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c @@ -0,0 +1,354 @@ +#include "hif_sdio.h" +#include "hif_sdio_chrdev.h" + + + +static int hif_sdio_proc(void * pvData); +static int hif_sdio_open(struct inode *inode, struct file *file); +static int hif_sdio_release(struct inode *inode, struct file *file); +static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); + + + +unsigned int hifSdioMajor = 0; + +#define COMBO_IOC_MAGIC 'h' +#define COMBO_IOCTL_GET_CHIP_ID _IOR(COMBO_IOC_MAGIC, 0, int) +#define COMBO_IOCTL_SET_CHIP_ID _IOW(COMBO_IOC_MAGIC, 1, int) + +MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = { + /* MT6620 */ /* Not an SDIO standard class device */ + { {SDIO_DEVICE(0x037A, 0x020A)}, 0x6620 }, /* SDIO1:FUNC1:WIFI */ + { {SDIO_DEVICE(0x037A, 0x020B)}, 0x6620 }, /* SDIO2:FUNC1:BT+FM+GPS */ + { {SDIO_DEVICE(0x037A, 0x020C)}, 0x6620 }, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT6628 */ /* SDIO1: Wi-Fi, SDIO2: BGF */ + { {SDIO_DEVICE(0x037A, 0x6628)}, 0x6628}, + +}; + + + +struct file_operations hifDevOps = +{ + .owner = THIS_MODULE, + .open = hif_sdio_open, + .release = hif_sdio_release, + .unlocked_ioctl = hif_sdio_unlocked_ioctl, + .read = hif_sdio_read, +}; + +struct class *pHifClass = NULL; +struct device *pHifDev = NULL; +UCHAR *HifClassName = "hifsdiod"; +UCHAR *kObjName = "hifsdiod"; + + +struct task_struct *gConIdQueryThread; +wait_queue_head_t gHifsdiodEvent; + +//OSAL_THREAD gConIdQueryThread; +//OSAL_EVENT gHifsdiodEvent; +UCHAR *gConIdQueryName = "consys-id-query"; +INT32 gComboChipId = -1; + + + +INT32 hifsdiod_start(void) +{ + int iRet = -1; + init_waitqueue_head(&gHifsdiodEvent); +#if 0 + osal_event_init(&gHifsdiodEvent); + gConIdQueryThread.pThreadData = (VOID *)NULL; + gConIdQueryThread.pThreadFunc = (VOID *)hif_sdio_proc; + osal_memcpy(gConIdQueryThread.threadName, gConIdQueryName , osal_strlen(gConIdQueryName)); + + + iRet = osal_thread_create(&gConIdQueryThread); + if (iRet < 0) + { + HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT1; + } +#else + gConIdQueryThread = kthread_create(hif_sdio_proc, NULL, gConIdQueryName); + if (NULL == gConIdQueryThread) + { + HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT1; + } + +#endif + +#if 0 + /* Start STPd thread*/ + iRet = osal_thread_run(&gConIdQueryThread); + if(iRet < 0) + { + HIF_SDIO_ERR_FUNC("osal_thread_run FAILS\n"); + goto ERR_EXIT1; + } +#else + if (gConIdQueryThread) { + wake_up_process(gConIdQueryThread); + } + else + { + goto ERR_EXIT1; + } +#endif + iRet = 0; + HIF_SDIO_INFO_FUNC("succeed\n"); + + return iRet; + +ERR_EXIT1: + HIF_SDIO_ERR_FUNC("failed\n"); + return iRet; + } + + +INT32 hifsdiod_stop(void) +{ + if (gConIdQueryThread) { + HIF_SDIO_INFO_FUNC("inform hifsdiod exit..\n"); + kthread_stop(gConIdQueryThread); + gConIdQueryThread = NULL; + } + return 0; +} + + +static int hif_sdio_proc(void * pvData) +{ + while (!kthread_should_stop()) + { + //HIF_SDIO_INFO_FUNC("enter sleep.\n"); + osal_msleep(10000); + //HIF_SDIO_INFO_FUNC("wakeup\n"); + } + HIF_SDIO_INFO_FUNC("hifsdiod exit.\n"); + return 0; +} + + +static int hif_sdio_open(struct inode *inode, struct file *file) +{ + HIF_SDIO_INFO_FUNC(" ++\n"); + HIF_SDIO_INFO_FUNC(" --\n"); + return 0; +} + +static int hif_sdio_release(struct inode *inode, struct file *file) +{ + HIF_SDIO_INFO_FUNC(" ++\n"); + HIF_SDIO_INFO_FUNC(" --\n"); + + return 0; +} + + +static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) + +{ + HIF_SDIO_INFO_FUNC(" ++\n"); + HIF_SDIO_INFO_FUNC(" --\n"); + + return 0; +} + +static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + + HIF_SDIO_DBG_FUNC("cmd (%d)\n", cmd); + + switch(cmd) + { + case COMBO_IOCTL_GET_CHIP_ID: + gComboChipId = 0x6628; + retval = gComboChipId; + HIF_SDIO_INFO_FUNC("get combo chip id: 0x%x\n", gComboChipId); + break; + case COMBO_IOCTL_SET_CHIP_ID: + gComboChipId = arg; + HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId); + break; + default: + HIF_SDIO_WARN_FUNC("unknown cmd (%d)\n", cmd); + retval = 0; + break; + } + return retval; +} + + +INT32 hif_sdio_is_chipid_valid (INT32 chipId) +{ + INT32 index = -1; + + INT32 left = 0; + INT32 middle = 0; + INT32 right = sizeof (gChipInfoArray) / sizeof (gChipInfoArray[0]) - 1; + if ((chipId < gChipInfoArray[left].chipId) || (chipId > gChipInfoArray[right].chipId)) + return index; + + middle = (left + right) / 2; + + while (left <= right) + { + if (chipId > gChipInfoArray[middle].chipId) + { + left = middle + 1; + } + else if (chipId < gChipInfoArray[middle].chipId) + { + right = middle - 1; + } + else + { + index = middle; + break; + } + middle = (left + right) / 2; + } + + if (0 > index) + { + HIF_SDIO_ERR_FUNC("no supported chipid found\n"); + } + else + { + HIF_SDIO_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId); + } + + return index; +} + +INT32 hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id *id) +{ + INT32 maxIndex = sizeof (gChipInfoArray) / sizeof (gChipInfoArray[0]); + INT32 index = 0; + struct sdio_device_id *localId = NULL; + INT32 chipId = -1; + for (index = 0; index < maxIndex; index++) + { + localId = &(gChipInfoArray[index].deviceId); + if ((localId->vendor == id->vendor) && (localId->device == id->device)) + { + chipId = gChipInfoArray[index].chipId; + HIF_SDIO_INFO_FUNC("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index, localId->vendor, localId->device, chipId); + gComboChipId = chipId; + break; + } + } + if (0 > chipId) + { + HIF_SDIO_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor, id->device); + } + + return chipId; +} + + +INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag) +{ + UINT32 timeSlotMs = 200; + UINT32 maxTimeSlot = 15; + UINT32 counter = 0; + //gComboChipId = 0x6628; + if (0 == waitFlag) + return gComboChipId; + if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) + return gComboChipId; + wmt_plat_pwr_ctrl(FUNC_ON); + wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_ON); + while (counter < maxTimeSlot) + { + if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) + break; + osal_msleep(timeSlotMs); + counter++; + } + + wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_OFF); + wmt_plat_pwr_ctrl(FUNC_OFF); + return gComboChipId; +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_query_chipid); + +INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId) +{ + + gComboChipId = chipId; + HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId); + + return gComboChipId; +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_tell_chipid); + +INT32 hif_sdio_create_dev_node(void) +{ + + INT32 iResult = -1; + + HIF_SDIO_DBG_FUNC( "++"); + iResult = register_chrdev(hifSdioMajor, kObjName, &hifDevOps); + if(0 > iResult) + { + HIF_SDIO_ERR_FUNC("register_chrdev failed.\n"); + iResult = -1; + } + else + { + hifSdioMajor = hifSdioMajor == 0 ? iResult : hifSdioMajor; + HIF_SDIO_INFO_FUNC("register_chrdev succeed, mtk_jajor = %d\n", hifSdioMajor); + pHifClass = class_create(THIS_MODULE, HifClassName); + if(IS_ERR(pHifClass)) + { + HIF_SDIO_ERR_FUNC("class_create error\n"); + iResult = -2; + } + else + { + pHifDev = device_create(pHifClass, NULL, MKDEV(hifSdioMajor, 0), NULL, HifClassName, "%d", 0); + if(IS_ERR(pHifDev)) + { + HIF_SDIO_ERR_FUNC("device_create error:%ld\n", PTR_ERR(pHifDev)); + iResult = -3; + } + else + { + HIF_SDIO_INFO_FUNC("device_create succeed\n"); + iResult = 0; + } + } + } + return iResult; +} + + +INT32 hif_sdio_remove_dev_node(void) +{ + if(pHifDev != NULL) + { + device_destroy(pHifClass, MKDEV(hifSdioMajor, 0)); + pHifDev = NULL; + } + if(pHifClass != NULL) + { + class_destroy(pHifClass); + pHifClass = NULL; + } + + if(hifSdioMajor != 0) + { + unregister_chrdev(hifSdioMajor, kObjName); + hifSdioMajor = 0; + } + return 0; +} + + diff --git a/drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h new file mode 100755 index 000000000000..4751937c2fdc --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h @@ -0,0 +1,311 @@ +/* +** $Id: $ +*/ + +/*! \file "hif_sdio.h" + \brief + + +*/ + +/* +** $Log: $ + * + * 07 25 2010 george.kuo + * + * Move hif_sdio driver to linux directory. + * + * 07 23 2010 george.kuo + * + * Add MT6620 driver source tree + * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver. +** +** +*/ + +#ifndef _HIF_SDIO_H +#define _HIF_SDIO_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_SDIO_DEBUG (0) /* 0:trun off debug msg and assert, 1:trun off debug msg and assert */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_exp.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CFG_CLIENT_COUNT (11) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +#define HIF_SDIO_LOG_LOUD 4 +#define HIF_SDIO_LOG_DBG 3 +#define HIF_SDIO_LOG_INFO 2 +#define HIF_SDIO_LOG_WARN 1 +#define HIF_SDIO_LOG_ERR 0 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Function info provided by client driver */ +typedef struct _MTK_WCN_HIF_SDIO_FUNCINFO MTK_WCN_HIF_SDIO_FUNCINFO; + +/* Client context provided by hif_sdio driver for the following function call */ +typedef UINT32 MTK_WCN_HIF_SDIO_CLTCTX; + +/* Callback functions provided by client driver */ +typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); +typedef INT32 (*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX); +typedef INT32 (*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX); + +/* Function info provided by client driver */ +struct _MTK_WCN_HIF_SDIO_FUNCINFO { + UINT16 manf_id; /* TPLMID_MANF: manufacturer ID */ + UINT16 card_id; /* TPLMID_CARD: card ID */ + UINT16 func_num; /* Function Number */ + UINT16 blk_sz; /* Function block size */ +}; + +/* Client info provided by client driver */ +typedef struct _MTK_WCN_HIF_SDIO_CLTINFO { + const MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */ + UINT32 func_tbl_size; /* supported function table info element number */ + MTK_WCN_HIF_SDIO_PROBE hif_clt_probe; /* callback function for probing */ + MTK_WCN_HIF_SDIO_REMOVE hif_clt_remove; /* callback function for removing */ + MTK_WCN_HIF_SDIO_IRQ hif_clt_irq; /* callback function for interrupt handling */ +} MTK_WCN_HIF_SDIO_CLTINFO; + +/* function info provided by registed function */ +typedef struct _MTK_WCN_HIF_SDIO_REGISTINFO { + const MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */ + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */ +} MTK_WCN_HIF_SDIO_REGISTINFO; + +/* Card info provided by probed function */ +typedef struct _MTK_WCN_HIF_SDIO_PROBEINFO { + struct sdio_func* func; /* probed sdio function pointer */ + void* private_data_p; /* clt's private data pointer */ + MTK_WCN_BOOL on_by_wmt; /* TRUE: on by wmt, FALSE: not on by wmt */ + /* added for sdio irq sync and mmc single_irq workaround */ + MTK_WCN_BOOL sdio_irq_enabled; /* TRUE: can handle sdio irq; FALSE: no sdio irq handling */ + INT8 clt_idx; /* registered function table info element number (initial value is -1) */ +} MTK_WCN_HIF_SDIO_PROBEINFO; + +/* work queue info needed by worker */ +typedef struct _MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO { + struct work_struct probe_work; /* work queue structure */ + MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p; /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */ + INT8 probe_idx; /* probed function table info element number (initial value is -1) */ +} MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO; + +/* global resource locks info of hif_sdio drv */ +typedef struct _MTK_WCN_HIF_SDIO_LOCKINFO { + spinlock_t probed_list_lock; /* spin lock for probed list */ + spinlock_t clt_list_lock; /* spin lock for client registed list */ +} MTK_WCN_HIF_SDIO_LOCKINFO; + +/* error code returned by hif_sdio driver (use NEGATIVE number) */ +typedef enum { + HIF_SDIO_ERR_SUCCESS = 0, + HIF_SDIO_ERR_FAIL = HIF_SDIO_ERR_SUCCESS - 1, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM = HIF_SDIO_ERR_FAIL - 1, + HIF_SDIO_ERR_DUPLICATED = HIF_SDIO_ERR_INVALID_PARAM - 1, + HIF_SDIO_ERR_UNSUP_MANF_ID = HIF_SDIO_ERR_DUPLICATED - 1, + HIF_SDIO_ERR_UNSUP_CARD_ID = HIF_SDIO_ERR_UNSUP_MANF_ID - 1, + HIF_SDIO_ERR_INVALID_FUNC_NUM = HIF_SDIO_ERR_UNSUP_CARD_ID - 1, + HIF_SDIO_ERR_INVALID_BLK_SZ = HIF_SDIO_ERR_INVALID_FUNC_NUM - 1, + HIF_SDIO_ERR_NOT_PROBED = HIF_SDIO_ERR_INVALID_BLK_SZ - 1, + HIF_SDIO_ERR_ALRDY_ON = HIF_SDIO_ERR_NOT_PROBED -1, + HIF_SDIO_ERR_ALRDY_OFF = HIF_SDIO_ERR_ALRDY_ON -1, + HIF_SDIO_ERR_CLT_NOT_REG = HIF_SDIO_ERR_ALRDY_OFF - 1, +} MTK_WCN_HIF_SDIO_ERR ; + +typedef struct _MTK_WCN_HIF_SDIO_CHIP_INFO_ +{ + struct sdio_device_id deviceId; + UINT32 chipId; +}MTK_WCN_HIF_SDIO_CHIP_INFO, *P_MTK_WCN_HIF_SDIO_CHIP_INFO; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + +/*! + * \brief A macro used to describe an SDIO function + * + * Fill an MTK_WCN_HIF_SDIO_FUNCINFO structure with function-specific information + * + * \param manf the 16 bit manufacturer id + * \param card the 16 bit card id + * \param func the 16 bit function number + * \param b_sz the 16 bit function block size + */ +#define MTK_WCN_HIF_SDIO_FUNC(manf, card, func, b_sz) \ + .manf_id = (manf), .card_id = (card), .func_num = (func), .blk_sz = (b_sz) + +#ifndef DFT_TAG +#define DFT_TAG "[HIF-SDIO]" +#endif + +extern UINT32 gHifSdioDbgLvl; + +#define HIF_SDIO_LOUD_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_LOUD) { osal_dbg_print(DFT_TAG"[L]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_DBG_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_DBG) { osal_dbg_print(DFT_TAG"[D]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_INFO_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_INFO) { osal_dbg_print(DFT_TAG"[I]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_WARN_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_WARN) { osal_dbg_print(DFT_TAG"[W]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} +#define HIF_SDIO_ERR_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_ERR) { osal_dbg_print(DFT_TAG"[E]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define HIF_SDIO_ASSERT(expr) if ( !(expr) ) { \ + osal_dbg_print("assertion failed! %s[%d]: %s\n",\ + __FUNCTION__, __LINE__, #expr); \ + osal_bug_on( !(expr) );\ + } +#else +#define HIF_SDIO_ASSERT(expr) do {} while(0) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*! + * \brief MTK hif sdio client registration function + * + * Client uses this function to do hif sdio registration + * + * \param pinfo a pointer of client's information + * + * \retval 0 register successfully + * \retval < 0 error code + */ +extern INT32 mtk_wcn_hif_sdio_client_reg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ); + +extern INT32 mtk_wcn_hif_sdio_client_unreg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ); + +extern INT32 mtk_wcn_hif_sdio_readb ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT8 pvb + ); + +extern INT32 mtk_wcn_hif_sdio_writeb ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT8 vb + ); + +extern INT32 mtk_wcn_hif_sdio_readl ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pvl + ); + +extern INT32 mtk_wcn_hif_sdio_writel ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT32 vl + ); + +extern INT32 mtk_wcn_hif_sdio_read_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ); + +extern INT32 mtk_wcn_hif_sdio_write_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ); + +extern void mtk_wcn_hif_sdio_set_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + void* private_data_p + ); + +extern void* mtk_wcn_hif_sdio_get_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx + ); + +extern INT32 mtk_wcn_hif_sdio_wmt_control( + WMT_SDIO_FUNC_TYPE func_type, + MTK_WCN_BOOL is_on + ); + +extern INT32 mtk_wcn_hif_sdio_bus_set_power ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 pwrState + ); + +extern void mtk_wcn_hif_sdio_get_dev( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + struct device **dev + ); + +extern INT32 mtk_wcn_hif_sdio_update_cb_reg( + int (*ts_update)(void) + ); + + +INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId); +INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ + + diff --git a/drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h new file mode 100755 index 000000000000..1aa756d4f624 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h @@ -0,0 +1,34 @@ + +#ifndef _HIF_SDIO_CHRDEV_H_ + +#define _HIF_SDIO_CHRDEV_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "wmt_exp.h" +#include "wmt_plat.h" +#ifdef CFG_WMT_PS_SUPPORT +#undef CFG_WMT_PS_SUPPORT +#endif + + +extern INT32 hif_sdio_create_dev_node(void); +extern INT32 hif_sdio_remove_dev_node(void); +extern INT32 hifsdiod_start(void); +extern INT32 hifsdiod_stop(void); +INT32 hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id *id); +INT32 hif_sdio_is_chipid_valid (INT32 chipId); + + + +#endif /*_HIF_SDIO_CHRDEV_H_*/ diff --git a/drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h b/drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h new file mode 100755 index 000000000000..ec4d5f19524d --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h @@ -0,0 +1,201 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + +#ifndef _MTK_WCN_CMB_STUB_H_ +#define _MTK_WCN_CMB_STUB_H_ + +#include + typedef enum { + COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ + COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ + COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ + COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ + COMBO_AUDIO_STATE_MAX = 4, + } COMBO_AUDIO_STATE; + + typedef enum { + COMBO_FUNC_TYPE_BT = 0, + COMBO_FUNC_TYPE_FM = 1, + COMBO_FUNC_TYPE_GPS = 2, + COMBO_FUNC_TYPE_WIFI = 3, + COMBO_FUNC_TYPE_WMT = 4, + COMBO_FUNC_TYPE_STP = 5, + COMBO_FUNC_TYPE_NUM = 6 + } COMBO_FUNC_TYPE; + + typedef enum { + COMBO_IF_UART = 0, + COMBO_IF_MSDC = 1, + COMBO_IF_MAX, + } COMBO_IF; + + + /****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + + + /* [GeorgeKuo] Stub functions for other kernel built-in modules to call. + * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo. + */ + //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl); + static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) { + //return mt_combo_audio_ctrl_ex(state, 1); + return 0; + } + //extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); + //extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); + + /* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control + * function on/off. + */ + //extern void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on); + //extern int board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on); +//#include jake +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum { + CMB_STUB_AIF_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ + CMB_STUB_AIF_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ + CMB_STUB_AIF_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ + CMB_STUB_AIF_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ + CMB_STUB_AIF_MAX = 4, +} CMB_STUB_AIF_X; + +/*COMBO_CHIP_AUDIO_PIN_CTRL*/ +typedef enum { + CMB_STUB_AIF_CTRL_DIS = 0, + CMB_STUB_AIF_CTRL_EN = 1, + CMB_STUB_AIF_CTRL_MAX = 2, +} CMB_STUB_AIF_CTRL; + +typedef void (*wmt_bgf_eirq_cb)(void); +typedef int (*wmt_aif_ctrl_cb)(CMB_STUB_AIF_X, CMB_STUB_AIF_CTRL); +typedef void (*wmt_func_ctrl_cb)(unsigned int, unsigned int); + +typedef struct _CMB_STUB_CB_ { + unsigned int size; //structure size + /*wmt_bgf_eirq_cb bgf_eirq_cb;*//* remove bgf_eirq_cb from stub. handle it in platform */ + wmt_aif_ctrl_cb aif_ctrl_cb; + wmt_func_ctrl_cb func_ctrl_cb; +} CMB_STUB_CB, *P_CMB_STUB_CB; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern int mtk_wcn_cmb_stub_reg (P_CMB_STUB_CB p_stub_cb); +extern int mtk_wcn_cmb_stub_unreg (void); + +extern int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); + +// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting +// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat +// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps +#if 0 +extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +#endif /* _MTK_WCN_CMB_STUB_H_ */ + + + + + + diff --git a/drivers/mtk_wcn_combo/common/linux/include/osal.h b/drivers/mtk_wcn_combo/common/linux/include/osal.h new file mode 100755 index 000000000000..aa21129ab0fd --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/osal.h @@ -0,0 +1,391 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _OSAL_H_ +#define _OSAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if WMT_PLAT_ALPS +#include +#endif +#include +#include +#include +#include +#include + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define OS_BIT_OPS_SUPPORT 1 + +#define _osal_inline_ inline + +#define MAX_THREAD_NAME_LEN 16 +#define MAX_WAKE_LOCK_NAME_LEN 16 +#define OSAL_OP_BUF_SIZE 64 +#define OSAL_OP_DATA_SIZE 32 +#define DBG_LOG_STR_SIZE 512 + +#define osal_sizeof(x) sizeof(x) + +#define osal_array_size(x) sizeof(x)/sizeof(x[0]) + +#ifndef NAME_MAX +#define NAME_MAX 256 +#endif + + +#define WMT_OP_BIT(x) (0x1UL << x) +#define WMT_OP_HIF_BIT WMT_OP_BIT(0) + + +#define RB_SIZE(prb) ((prb)->size) +#define RB_MASK(prb) (RB_SIZE(prb) - 1) +#define RB_COUNT(prb) ((prb)->write - (prb)->read) +#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) +#define RB_EMPTY(prb) ((prb)->write == (prb)->read) + +#define RB_INIT(prb, qsize) \ + { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ + } + +#define RB_PUT(prb, value) \ +{ \ + if (!RB_FULL( prb )) { \ + (prb)->queue[ (prb)->write & RB_MASK(prb) ] = value; \ + ++((prb)->write); \ + } \ + else { \ + osal_assert(!RB_FULL(prb)); \ + } \ +} + +#define RB_GET(prb, value) \ +{ \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[ (prb)->read & RB_MASK(prb) ]; \ + ++((prb)->read); \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + osal_assert(!RB_EMPTY(prb)); \ + } \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + + +typedef VOID (*P_TIMEOUT_HANDLER)(ULONG); +typedef INT32 (*P_COND)(VOID *); + +typedef struct _OSAL_TIMER_ +{ + struct timer_list timer; + P_TIMEOUT_HANDLER timeoutHandler; + ULONG timeroutHandlerData; +}OSAL_TIMER, *P_OSAL_TIMER; + +typedef struct _OSAL_UNSLEEPABLE_LOCK_ +{ + spinlock_t lock; + ULONG flag; +}OSAL_UNSLEEPABLE_LOCK, *P_OSAL_UNSLEEPABLE_LOCK; + +typedef struct _OSAL_SLEEPABLE_LOCK_ +{ + struct mutex lock; +}OSAL_SLEEPABLE_LOCK, *P_OSAL_SLEEPABLE_LOCK; + + +typedef struct _OSAL_SIGNAL_ +{ + struct completion comp; + UINT32 timeoutValue; +}OSAL_SIGNAL, *P_OSAL_SIGNAL; + + +typedef struct _OSAL_EVENT_ +{ + wait_queue_head_t waitQueue; +// VOID *pWaitQueueData; + UINT32 timeoutValue; + INT32 waitFlag; + +}OSAL_EVENT, *P_OSAL_EVENT; + +typedef struct _OSAL_THREAD_ +{ + struct task_struct *pThread; + VOID *pThreadFunc; + VOID *pThreadData; + char threadName[MAX_THREAD_NAME_LEN]; +}OSAL_THREAD, *P_OSAL_THREAD; + +typedef struct _OSAL_FIFO_ +{ + /*fifo definition*/ + VOID *pFifoBody; + spinlock_t fifoSpinlock; + /*fifo operations*/ + INT32 (*FifoInit)(struct _OSAL_FIFO_ *pFifo, UINT8 *buf, UINT32); + INT32 (*FifoDeInit)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoReset)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoSz)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoAvailSz)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoLen)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoIsEmpty)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoIsFull)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoDataIn)(struct _OSAL_FIFO_ *pFifo, const VOID *buf, UINT32 len); + INT32 (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, void *buf, UINT32 len); +} OSAL_FIFO, *P_OSAL_FIFO; + +typedef struct firmware osal_firmware; + +typedef struct _OSAL_OP_DAT { + UINT32 opId; // Event ID + UINT32 u4InfoBit; // Reserved + UINT32 au4OpData[OSAL_OP_DATA_SIZE]; // OP Data +} OSAL_OP_DAT, *P_OSAL_OP_DAT; + +typedef struct _OSAL_LXOP_ { + OSAL_OP_DAT op; + OSAL_SIGNAL signal; + INT32 result; +} OSAL_OP, *P_OSAL_OP; + +typedef struct _OSAL_LXOP_Q { + OSAL_SLEEPABLE_LOCK sLock; + UINT32 write; + UINT32 read; + UINT32 size; + P_OSAL_OP queue[OSAL_OP_BUF_SIZE]; +} OSAL_OP_Q, *P_OSAL_OP_Q; + +typedef struct _OSAL_WAKE_LOCK_ +{ + struct wake_lock wake_lock; + UINT8 name[MAX_WAKE_LOCK_NAME_LEN]; +} OSAL_WAKE_LOCK, *P_OSAL_WAKE_LOCK; +#if 1 +typedef struct _OSAL_BIT_OP_VAR_ +{ + ULONG data; + OSAL_UNSLEEPABLE_LOCK opLock; +}OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR; +#else +#define OSAL_BIT_OP_VAR ULONG +#define P_OSAL_BIT_OP_VAR ULONG* + + +#endif +typedef UINT32 (*P_OSAL_EVENT_CHECKER)(P_OSAL_THREAD pThread); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern UINT32 osal_strlen(const char *str); +extern INT32 osal_strcmp(const char *dst, const char *src); +extern INT32 osal_strncmp(const char *dst, const char *src, UINT32 len); +extern char * osal_strcpy(char *dst, const char *src); +extern char * osal_strncpy(char *dst, const char *src, UINT32 len); +extern char * osal_strcat(char *dst, const char *src); +extern char * osal_strncat(char *dst, const char *src, UINT32 len); +extern char * osal_strchr(const char *str, UINT8 c); +extern char * osal_strsep(char **str, const char *c); +extern void osal_bug_on(unsigned long val); + +extern LONG osal_strtol(const char *str, char **c, UINT32 adecimal); +extern INT32 osal_snprintf(char *buf, UINT32 len, const char*fmt, ...); + +extern INT32 osal_print(const char *str, ...); +extern INT32 osal_dbg_print(const char *str, ...); + + +extern INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line); +extern INT32 osal_sprintf(char *str, const char *format, ...); +extern VOID* osal_malloc(UINT32 size); +extern VOID osal_free(const VOID *dst); +extern VOID* osal_memset(VOID *buf, INT32 i, UINT32 len); +extern VOID* osal_memcpy(VOID *dst, const VOID *src, UINT32 len); +extern INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len); + +extern INT32 osal_msleep(UINT32 ms); + +extern INT32 osal_timer_create(P_OSAL_TIMER); +extern INT32 osal_timer_start(P_OSAL_TIMER, UINT32); +extern INT32 osal_timer_stop(P_OSAL_TIMER); +extern INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer); +extern INT32 osal_timer_modify(P_OSAL_TIMER, UINT32); +extern INT32 osal_timer_delete(P_OSAL_TIMER); + +extern INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size); +extern VOID osal_fifo_deinit(P_OSAL_FIFO pFifo); +extern INT32 osal_fifo_reset(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +extern UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +extern UINT32 osal_fifo_len(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo); + +extern INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_lock(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK plock); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock));} +#else +extern INT32 osal_unsleepable_lock_init (P_OSAL_UNSLEEPABLE_LOCK ); +#endif +extern INT32 osal_lock_unsleepable_lock (P_OSAL_UNSLEEPABLE_LOCK ); +extern INT32 osal_unlock_unsleepable_lock (P_OSAL_UNSLEEPABLE_LOCK ); +extern INT32 osal_unsleepable_lock_deinit (P_OSAL_UNSLEEPABLE_LOCK ); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_sleepable_lock_init(l) { mutex_init(&((l)->lock));} +#else +extern INT32 osal_sleepable_lock_init (P_OSAL_SLEEPABLE_LOCK ); +#endif +extern INT32 osal_lock_sleepable_lock (P_OSAL_SLEEPABLE_LOCK ); +extern INT32 osal_unlock_sleepable_lock (P_OSAL_SLEEPABLE_LOCK ); +extern INT32 osal_sleepable_lock_deinit (P_OSAL_SLEEPABLE_LOCK ); + +extern INT32 osal_signal_init (P_OSAL_SIGNAL); +extern INT32 osal_wait_for_signal (P_OSAL_SIGNAL); +extern INT32 +osal_wait_for_signal_timeout ( + P_OSAL_SIGNAL + ); +extern INT32 +osal_raise_signal ( + P_OSAL_SIGNAL + ); +extern INT32 +osal_signal_deinit ( + P_OSAL_SIGNAL + ); + +extern INT32 osal_event_init(P_OSAL_EVENT); +extern INT32 osal_wait_for_event(P_OSAL_EVENT, P_COND , void *); +extern INT32 osal_wait_for_event_timeout(P_OSAL_EVENT , P_COND , void *); +extern INT32 osal_trigger_event(P_OSAL_EVENT); + +extern INT32 osal_event_deinit (P_OSAL_EVENT); + +extern INT32 osal_thread_create(P_OSAL_THREAD); +extern INT32 osal_thread_run(P_OSAL_THREAD); +extern INT32 osal_thread_should_stop(P_OSAL_THREAD); +extern INT32 osal_thread_stop(P_OSAL_THREAD); +/*extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/ +extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER); +/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/ +extern INT32 osal_thread_destroy(P_OSAL_THREAD); + +extern INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); + +extern INT32 osal_dbg_assert_aee(const char *module, const char *detail_description); +extern INT32 osal_gettimeofday(PINT32 sec, PINT32 usec); +extern INT32 osal_printtimeofday(const PUINT8 prefix); + +extern VOID +osal_buffer_dump ( + const UINT8 *buf, + const UINT8 *title, + UINT32 len, + UINT32 limit + ); + +extern UINT32 osal_op_get_id(P_OSAL_OP pOp); +extern MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp); +extern VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result); + +extern UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#define osal_err_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg) +#define osal_warn_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg) +#define osal_info_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg) +#define osal_load_print(fmt, arg...) osal_print(KERN_DEBUG fmt, ##arg) +#define osal_assert(condition) if (!(condition)) {osal_err_print("%s, %d, (%s)\n", __FILE__, __LINE__, #condition);} + +#endif /* _OSAL_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h b/drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h new file mode 100755 index 000000000000..e486576b9647 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h @@ -0,0 +1,46 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + +#ifndef _OSAL_TYPEDEF_H_ +#define _OSAL_TYPEDEF_H_ + +typedef void VOID; +typedef void *PVOID; + +typedef char CHAR; +typedef char *PCHAR; +typedef signed char INT8; +typedef signed char *PINT8; +typedef unsigned char UINT8; +typedef unsigned char *PUINT8; +typedef unsigned char UCHAR; +typedef unsigned char *PUCHAR; + +typedef signed short INT16; +typedef signed short *PINT16; +typedef unsigned short UINT16; +typedef unsigned short *PUINT16; + +typedef signed long LONG; +typedef signed long *PLONG; + +typedef signed int INT32; +typedef signed int *PINT32; +typedef unsigned int UINT32; +typedef unsigned int *PUINT32; + +typedef unsigned long ULONG; +typedef unsigned long *PULONG; + +typedef int MTK_WCN_BOOL; +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +#endif /*_OSAL_TYPEDEF_H_*/ + diff --git a/drivers/mtk_wcn_combo/common/linux/include/stp_dbg.h b/drivers/mtk_wcn_combo/common/linux/include/stp_dbg.h new file mode 100755 index 000000000000..7a956e360756 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/stp_dbg.h @@ -0,0 +1,229 @@ +#ifndef _STP_DEBUG_H_ +#define _STP_DEBUG_H_ + +#include +#include "osal.h" + +#define CONFIG_LOG_STP_INTERNAL + +#if 1//#ifndef CONFIG_LOG_STP_INTERNAL +#define STP_PKT_SZ 16 +#define STP_DMP_SZ 2048 +#define STP_PKT_NO 2048 + +#define STP_DBG_LOG_ENTRY_NUM 2048 +#define STP_DBG_LOG_ENTRY_SZ 2048 + +#else + +#define STP_PKT_SZ 16 +#define STP_DMP_SZ 16 +#define STP_PKT_NO 16 + +#define STP_DBG_LOG_ENTRY_NUM 28 +#define STP_DBG_LOG_ENTRY_SZ 64 + + +#endif + + +typedef enum { + STP_DBG_EN = 0, + STP_DBG_PKT = 1, + STP_DBG_DR = 2, + STP_DBG_FW_ASSERT = 3, + STP_DBG_FW_LOG = 4, + STP_DBG_FW_DMP = 5, + STP_DBG_MAX +}STP_DBG_OP_T; + +typedef enum { + STP_DBG_PKT_FIL_ALL = 0, + STP_DBG_PKT_FIL_BT = 1, + STP_DBG_PKT_FIL_GPS = 2, + STP_DBG_PKT_FIL_FM = 3, + STP_DBG_PKT_FIL_WMT = 4, + STP_DBG_PKT_FIL_MAX +} STP_DBG_PKT_FIL_T; + +static char * const gStpDbgType[]={ + "< BT>", + "< FM>", + "", + "", + "", + "", + "", + "" +}; + + +typedef enum { + STP_DBG_DR_MAX = 0, +} STP_DBG_DR_FIL_T; + +typedef enum { + STP_DBG_FW_MAX = 0, +} STP_DBG_FW_FIL_T; + +typedef enum { + PKT_DIR_RX = 0, + PKT_DIR_TX +} STP_DBG_PKT_DIR_T; + +/*simple log system ++*/ + +typedef struct { + int id; /*type: 0. pkt trace 1. fw info 2. assert info 3. trace32 dump . -1. linked to the the previous*/ + int len; + char buffer[STP_DBG_LOG_ENTRY_SZ]; +} MTKSTP_LOG_ENTRY_T; + +typedef struct log_sys { + MTKSTP_LOG_ENTRY_T queue[STP_DBG_LOG_ENTRY_NUM]; + unsigned int size; + unsigned int in; + unsigned int out; + spinlock_t lock; +} MTKSTP_LOG_SYS_T; +/*--*/ + +typedef struct stp_dbg_pkt_hdr{ + //packet information + unsigned int sec; + unsigned int usec; + unsigned int dbg_type; + unsigned int dmy; + unsigned int no; + unsigned int dir; + + //packet content + unsigned int type; + unsigned int len; + unsigned int ack; + unsigned int seq; + unsigned int chs; + unsigned int crc; +}STP_DBG_HDR_T; + +typedef struct stp_dbg_pkt{ + struct stp_dbg_pkt_hdr hdr; + unsigned char raw[STP_DMP_SZ]; +}STP_PACKET_T; + +typedef struct mtkstp_dbg_t{ + /*log_sys*/ + int pkt_trace_no; + void *btm; + int is_enable; + MTKSTP_LOG_SYS_T *logsys; +}MTKSTP_DBG_T; + +extern void aed_combo_exception(const int *, int, const int *, int, const char *); + +#define STP_CORE_DUMP_TIMEOUT 5*60*1000 // default 5minutes +#define STP_OJB_NAME_SZ 20 +#define STP_CORE_DUMP_INFO_SZ 500 +typedef enum wcn_compress_algorithm_t { + GZIP = 0, + BZIP2 = 1, + RAR = 2, + LMA = 3, + MAX +}WCN_COMPRESS_ALG_T; + +typedef INT32 (*COMPRESS_HANDLER)(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, INT32 finish); +typedef struct wcn_compressor_t { + // current object name + UINT8 name[STP_OJB_NAME_SZ + 1]; + + // buffer for raw data, named L1 + PUINT8 L1_buf; + INT32 L1_buf_sz; + INT32 L1_pos; + + // target buffer, named L2 + PUINT8 L2_buf; + INT32 L2_buf_sz; + INT32 L2_pos; + + // compress state + UINT8 f_done; + UINT16 reserved; + UINT32 uncomp_size; + UINT32 crc32; + + // compress algorithm + UINT8 f_compress_en; + WCN_COMPRESS_ALG_T compress_type; + void *worker; + COMPRESS_HANDLER handler; +}WCN_COMPRESSOR_T, *P_WCN_COMPRESSOR_T; + +P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz); +INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T compressor); +INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T compressor, PUINT8 buf, INT32 len, INT32 finish); +INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T compressor, PUINT8 *pbuf, PINT32 len); +INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T compressor, UINT8 enable, WCN_COMPRESS_ALG_T type); + +typedef enum core_dump_state_t { + CORE_DUMP_INIT = 0, + CORE_DUMP_DOING, + CORE_DUMP_TIMEOUT, + CORE_DUMP_DONE, + CORE_DUMP_MAX +}CORE_DUMP_STA; + +typedef struct core_dump_t { + // compress dump data and buffered + P_WCN_COMPRESSOR_T compressor; + + // timer for monitor timeout + OSAL_TIMER dmp_timer; + UINT32 timeout; + + OSAL_SLEEPABLE_LOCK dmp_lock; + + // state machine for core dump flow + CORE_DUMP_STA sm; + + // dump info + CHAR info[STP_CORE_DUMP_INFO_SZ + 1]; +} WCN_CORE_DUMP_T, *P_WCN_CORE_DUMP_T; + +P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 timeout); +INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp); +INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len); +INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 len); +INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout); +extern INT32 wcn_core_dump_flush(INT32 rst); + +extern int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg); +extern int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg); +extern MTKSTP_DBG_T *stp_dbg_init(void *); +extern int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg); +extern int stp_dbg_dmp_out_ex (char *buf, int *len); +extern int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len); +extern int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg); +extern char +stp_dbg_nl_send( + char * aucMsg, + unsigned char cmd + ); + +extern INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd); + +extern int +stp_dbg_log_pkt ( + MTKSTP_DBG_T *stp_dbg, + int dbg_type, + int type, + int ack_no, + int seq_no, + int crc, + int dir, + int len, + const unsigned char *body); +extern int stp_dbg_log_ctrl (unsigned int on); +#endif /* end of _STP_DEBUG_H_ */ + diff --git a/drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h b/drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h new file mode 100755 index 000000000000..82f5118ff3e5 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h @@ -0,0 +1,252 @@ +/* +** $Id: $ +*/ + +/*! \file "stp_sdio.h" + \brief + + +*/ + +/* +** $Log: $ +*/ + +#ifndef _STP_SDIO_H +#define _STP_SDIO_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + + +#define KMALLOC_UPDATE 1 + +#if 0 // NO support for multiple STP-SDIO instances (multiple MT6620) on a single host +#define STP_SDIO_HOST_COUNT (1) +#define STP_SDIO_ONLY_ONE_HOST (0) +#endif +#define STP_SDIO_POLL_OWNBACK_INTR (1) + +#define STP_SDIO_NEW_TXRING (0) +/* George: Keep old (0) codes for debugging only! + * Use new code (1) for SQC and MP! + */ + +#define STP_SDIO_OWN_THREAD (1) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "osal.h" +#include "hif_sdio.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Common HIF register address */ +#define CCIR (0x0000) +#define CHLPCR (0x0004) +#define CSDIOCSR (0x0008) +#define CHCR (0x000c) +#define CHISR (0x0010) +#define CHIER (0x0014) +#define CTDR (0x0018) +#define CRDR (0x001c) +#define CTFSR (0x0020) +#define CRPLR (0x0024) + +/* Common HIF register bit field address */ +/* CHLPCR */ +#define C_FW_OWN_REQ_CLR (0x00000200) +#define C_FW_OWN_REQ_SET (0x00000100) +#define C_FW_INT_EN_CLR (0x00000002) +#define C_FW_INT_EN_SET (0x00000001) +#define C_FW_COM_DRV_OWN (0x00000100) + +/* CHIER */ +#define CHISR_EN_15_7 (0x0000ff80) +#define CHISR_EN_3_0 (0x0000000f) +/* CHISR */ +#define RX_PKT_LEN (0xffff0000) +#define FIRMWARE_INT (0x0000fe00) +#define TX_FIFO_OVERFLOW (0x00000100) +#define FW_INT_IND_INDICATOR (0x00000080) +#define TX_COMPLETE_COUNT (0x00000070) +#define TX_UNDER_THOLD (0x00000008) +#define TX_EMPTY (0x00000004) +#define RX_DONE (0x00000002) +#define FW_OWN_BACK_INT (0x00000001) + +/* hardware settings */ +#define STP_SDIO_TX_FIFO_SIZE (2080UL) +#define STP_SDIO_RX_FIFO_SIZE (2304UL) /* 256*9 */ +#define STP_SDIO_TX_PKT_MAX_CNT (7) /* Max outstanding tx pkt count, as defined in TX_COMPLETE_COUNT */ +#define STP_SDIO_HDR_SIZE (4) /* hw,fw,sw follow the same format: 2 bytes length + 2 bytes reserved */ + +/* sdio bus settings */ +#define STP_SDIO_BLK_SIZE (512UL) + +/* software driver settings */ +#define STP_SDIO_TX_BUF_CNT (16UL)/*(7)*/ +#define STP_SDIO_TX_BUF_CNT_MASK (STP_SDIO_TX_BUF_CNT - 1) +#define STP_SDIO_TX_PKT_LIST_SIZE (STP_SDIO_TX_BUF_CNT) /* must be 2^x now... */ +#define STP_SDIO_TX_PKT_LIST_SIZE_MASK (STP_SDIO_TX_PKT_LIST_SIZE - 1) + +/* tx buffer size for a single entry */ +/* George: SHALL BE a multiple of the used BLK_SIZE!! */ +#if 1 +/* round up: 512*5 = 2560 > 2080 */ +#define STP_SDIO_TX_ENTRY_SIZE ((STP_SDIO_TX_FIFO_SIZE + (STP_SDIO_BLK_SIZE - 1)) & ~(STP_SDIO_BLK_SIZE - 1)) +#else +/* round down: 512*4 = 2048 < 2080 */ +#define STP_SDIO_TX_MAX_BLK_CNT (STP_SDIO_TX_FIFO_SIZE / STP_SDIO_BLK_SIZE) +#define STP_SDIO_TX_ENTRY_SIZE (STP_SDIO_TX_MAX_BLK_CNT * STP_SDIO_BLK_SIZE) +#endif + +/*software rx buffer size */ +/*#define STP_SDIO_RX_BUF_SIZE (STP_SDIO_RX_FIFO_SIZE)*/ +/* George: SHALL BE a multiple of the used BLK_SIZE!! */ +#if 1 +/* round up: 512*5 = 2560 > 2304 */ +#define STP_SDIO_RX_BUF_SIZE ((STP_SDIO_RX_FIFO_SIZE + (STP_SDIO_BLK_SIZE - 1)) & ~(STP_SDIO_BLK_SIZE - 1)) +#else +/* round down: 512*4 = 2048 < 2304 */ +#define STP_SDIO_RX_MAX_BLK_CNT (STP_SDIO_RX_FIFO_SIZE / STP_SDIO_BLK_SIZE) +#define STP_SDIO_RX_BUF_SIZE (STP_SDIO_RX_MAX_BLK_CNT * STP_SDIO_BLK_SIZE) +#endif + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* HIF's local packet buffer variables for Tx/Rx */ +typedef struct _MTK_WCN_STP_SDIO_PKT_BUF { + /* Tx entry ring buffer. Entry size is aligned to SDIO block size. */ +#if KMALLOC_UPDATE + UINT8 *tx_buf; +#else + UINT8 tx_buf[STP_SDIO_TX_BUF_CNT][STP_SDIO_TX_ENTRY_SIZE]; +#endif + + /* Tx size ring buffer. Record valid data size in tx_buf. */ + UINT32 tx_buf_sz[STP_SDIO_TX_BUF_CNT]; + /* Tx debug timestamp: 1st time when the entry is filled with data */ + UINT32 tx_buf_ts[STP_SDIO_TX_BUF_CNT]; +#if KMALLOC_UPDATE + UINT8 *rx_buf; +#else + UINT8 rx_buf[STP_SDIO_RX_BUF_SIZE]; /* Rx buffer (not ring) */ +#endif +#if STP_SDIO_NEW_TXRING + UINT32 wr_cnt; /* Tx entry ring buffer write count */ + UINT32 rd_cnt; /* Tx entry ring buffer read count */ + spinlock_t rd_cnt_lock; /* Tx entry ring buffer read count spin lock */ +#else + UINT8 wr_idx; /* Tx ring buffer write index */ /*George: obsolete*/ + UINT8 rd_idx; /* Tx ring buffer read index *//*George: obsolete*/ + spinlock_t rd_idx_lock; /* spin lock for Tx ring buffer read index */ +#endif + MTK_WCN_BOOL full_flag; /* Tx entry ring buffer full flag (TRUE: full, FALSE: not full) */ + /* save interrupt status flag for Tx entry ring buf spin lock */ + unsigned long rd_irq_flag; + /* wait queue head for Tx entry ring buf full case */ + wait_queue_head_t fullwait_q; +} MTK_WCN_STP_SDIO_PKT_BUF; + +/* Tx packet list information */ +typedef struct _MTK_WCN_STP_SDIO_Tx_Pkt_LIST { + UINT32 pkt_rd_cnt; + UINT32 pkt_wr_cnt; + UINT16 pkt_size_list[STP_SDIO_TX_PKT_LIST_SIZE]; /*max length is FIFO Size */ + UINT32 out_ts[STP_SDIO_TX_PKT_LIST_SIZE]; + UINT32 in_ts[STP_SDIO_TX_PKT_LIST_SIZE]; +} MTK_WCN_STP_SDIO_Tx_Pkt_LIST; + +/* STP HIF firmware information */ +typedef struct _MTK_WCN_STP_SDIO_FIRMWARE_INFO { + UINT32 tx_fifo_size; /* Current left tx FIFO size */ + UINT32 tx_packet_num; /* Current outstanding tx packet (0~7) */ + atomic_t tx_comp_num; /* Current total tx ok but fifo size not released packet count */ +} MTK_WCN_STP_SDIO_FIRMWARE_INFO; + +/* STP SDIO private information */ +typedef struct _MTK_WCN_STP_SDIO_PRIVATE_INFO { + UINT8 stp_sdio_host_idx; +} MTK_WCN_STP_SDIO_PRIVATE_INFO; + +/* STP SDIO host information */ +typedef struct _MTK_WCN_STP_SDIO_HIF_INFO { + MTK_WCN_HIF_SDIO_CLTCTX sdio_cltctx; + MTK_WCN_STP_SDIO_PKT_BUF pkt_buf; + MTK_WCN_STP_SDIO_Tx_Pkt_LIST tx_pkt_list; + UINT32 rx_pkt_len; /* George: use 32-bit for efficiency. Correct name to pkt for packet */ + MTK_WCN_STP_SDIO_FIRMWARE_INFO firmware_info; + MTK_WCN_STP_SDIO_PRIVATE_INFO private_info; +#if STP_SDIO_OWN_THREAD + //struct tasklet_struct tx_rx_job; + OSAL_THREAD tx_rx_thread; + INT32 irq_pending; + INT32 sleep_flag; + INT32 wakeup_flag; + INT32 awake_flag; + OSAL_EVENT tx_rx_event; + OSAL_SIGNAL isr_check_complete; +#endif + struct work_struct tx_work; + struct work_struct rx_work; +} MTK_WCN_STP_SDIO_HIF_INFO; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* STP_SDIO_TX_PKT_LIST_SIZE must be 2^x */ +#define STP_SDIO_GET_PKT_AR_IDX(idx) ((idx) & STP_SDIO_TX_PKT_LIST_SIZE_MASK) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*! + * \brief MTK hif sdio client registration function + * + * Client uses this function to do hif sdio registration + * + * \param pinfo a pointer of client's information + * + * \retval 0 register successfully + * \retval < 0 error code + */ +extern INT32 +mtk_wcn_hif_sdio_client_reg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ); + +extern INT32 +mtk_wcn_stp_sdio_do_own_clr (void); + +//extern INT32 +//mtk_wcn_stp_sdio_do_own_set (void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _STP_SDIO_H */ + diff --git a/drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h b/drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h new file mode 100755 index 000000000000..81c17c777de5 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h @@ -0,0 +1,16 @@ + + +#ifndef _WMT_DEV_H_ +#define _WMT_DEV_H_ + + +#include "osal.h" + +extern VOID wmt_dev_rx_event_cb (VOID); +extern INT32 wmt_dev_rx_timeout (P_OSAL_EVENT pEvent); +extern INT32 wmt_dev_patch_get (UCHAR *pPatchName, osal_firmware **ppPatch,INT32 padSzBuf); +extern INT32 wmt_dev_patch_put(osal_firmware **ppPatch); +extern VOID wmt_dev_patch_info_free(VOID); + + +#endif /*_WMT_DEV_H_*/ diff --git a/drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h b/drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h new file mode 100755 index 000000000000..d1aeaccf1fa8 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h @@ -0,0 +1,20 @@ +#ifndef _WMT_TM_H +#define _WMT_TM_H +#if WMT_PLAT_ALPS + +#define CONFIG_THERMAL_OPEN +#if defined(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OPEN) + + struct wmt_thermal_ctrl_ops { + int (*query_temp)(void); + int (*set_temp)(int); + }; + + int wmt_tm_init(struct wmt_thermal_ctrl_ops *ops); + int wmt_tm_deinit(void); + int wmt_tm_init_rt(void); + int wmt_tm_deinit_rt(void); +#endif + +#endif +#endif diff --git a/drivers/mtk_wcn_combo/common/linux/osal.c b/drivers/mtk_wcn_combo/common/linux/osal.c new file mode 100755 index 000000000000..ae93b437ab6e --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/osal.c @@ -0,0 +1,1297 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "osal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ +static UINT16 const crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*string operations*/ +_osal_inline_ UINT32 osal_strlen(const char *str) +{ + return strlen(str); +} + +_osal_inline_ INT32 osal_strcmp(const char *dst, const char *src) +{ + return strcmp(dst, src); +} + +_osal_inline_ INT32 osal_strncmp(const char *dst, const char *src, UINT32 len) +{ + return strncmp(dst, src, len); +} + +_osal_inline_ char * osal_strcpy(char *dst, const char *src) +{ + return strcpy(dst, src); +} + +_osal_inline_ char * osal_strncpy(char *dst, const char *src, UINT32 len) +{ + return strncpy(dst, src, len); +} + + +_osal_inline_ char * osal_strcat(char *dst, const char *src) +{ + return strcat(dst, src); +} + +_osal_inline_ char * osal_strncat(char *dst, const char *src, UINT32 len) +{ + return strncat(dst, src, len); +} + +_osal_inline_ char * osal_strchr(const char *str, UINT8 c) +{ + return strchr(str, c); +} + + +_osal_inline_ char * osal_strsep(char **str, const char *c) +{ + return strsep(str, c); +} + +_osal_inline_ void osal_bug_on(unsigned long val) +{ + BUG_ON(val); +} +_osal_inline_ LONG osal_strtol(const char *str, char **c, UINT32 adecimal) +{ + return simple_strtol(str, c, adecimal); +} + +INT32 osal_snprintf(char *buf, UINT32 len, const char*fmt, ...) +{ + INT32 iRet = 0; + va_list args; + + /*va_start(args, fmt);*/ + va_start(args, fmt); + /*iRet = snprintf(buf, len, fmt, args);*/// TODO: [FixMe][GeorgeKuo] BUG? + iRet = vsnprintf(buf, len, fmt, args); + va_end(args); + + return iRet; +} + +INT32 osal_print(const char *str, ...) +{ + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + printk("%s",tempString); + + return 0; +} + + +INT32 osal_dbg_print(const char *str, ...) +{ + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + printk(KERN_DEBUG "%s",tempString); + + return 0; +} + + +INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line) +{ + if (!expr){ + printk("%s (%d)\n", file, line); + /*BUG_ON(!expr);*/ +#ifdef CFG_COMMON_GPIO_DBG_PIN +//package this part + mt_set_gpio_out(GPIO70, GPIO_OUT_ZERO); + printk("toggle GPIO70\n"); + udelay(10); + mt_set_gpio_out(GPIO70, GPIO_OUT_ONE); +#endif + return 1; + } + return 0; + + +} + +INT32 osal_dbg_assert_aee(const char *module, const char *detail_description){ + osal_err_print("[WMT-ASSERT]""[E][Module]:%s, [INFO]%s\n", module, detail_description); + +#if WMT_PLAT_ALPS + aee_kernel_warning( + module, + detail_description); +#endif + return 0; +} + +INT32 osal_sprintf(char *str, const char *format, ...) +{ + INT32 iRet = 0; + va_list args; + + va_start(args, format); + iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args); + va_end(args); + + return iRet; +} + +_osal_inline_ VOID* osal_malloc(UINT32 size) +{ + return vmalloc(size); +} + + +_osal_inline_ VOID osal_free(const VOID *dst) +{ + vfree(dst); +} + +_osal_inline_ VOID* osal_memset(VOID *buf, INT32 i, UINT32 len) +{ + return memset(buf, i, len); +} + + +_osal_inline_ VOID* osal_memcpy(VOID *dst, const VOID *src, UINT32 len) +{ + return memcpy(dst, src, len); +} + + +_osal_inline_ INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len) +{ + return memcmp(buf1, buf2, len); +} + +_osal_inline_ UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length) +{ + UINT16 crc = 0; + UINT32 i = 0; + + //FIXME: Add STP checksum feature + crc = 0; + for (i = 0; i < length; i++, buffer++) + { + crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; + } + return crc; +} + + + + +/* + *OSAL layer Thread Opeartion releated APIs + * + * +*/ +_osal_inline_ INT32 +osal_thread_create ( + P_OSAL_THREAD pThread + ) +{ + pThread->pThread = kthread_create(pThread->pThreadFunc, + pThread->pThreadData, + pThread->threadName); + if (NULL == pThread->pThread) { + return -1; + } + return 0; +} +_osal_inline_ INT32 +osal_thread_run ( + P_OSAL_THREAD pThread + ) +{ + if (pThread->pThread) { + wake_up_process(pThread->pThread); + return 0; + } + else { + return -1; + } +} + +_osal_inline_ INT32 +osal_thread_stop ( + P_OSAL_THREAD pThread + ) +{ + INT32 iRet; + if ( (pThread) && (pThread->pThread) ) { + iRet = kthread_stop(pThread->pThread); + //pThread->pThread = NULL; + return iRet; + } + return -1; +} + + +_osal_inline_ INT32 +osal_thread_should_stop ( + P_OSAL_THREAD pThread + ) +{ + if ( (pThread) && (pThread->pThread) ) { + return kthread_should_stop(); + } + else { + return 1; + } +} + + +_osal_inline_ INT32 +osal_thread_wait_for_event ( + P_OSAL_THREAD pThread, + P_OSAL_EVENT pEvent, + P_OSAL_EVENT_CHECKER pChecker + ) +{ +/* P_DEV_WMT pDevWmt;*/ + + if ( (pThread) && (pThread->pThread) && (pEvent) && (pChecker)) { +/* pDevWmt = (P_DEV_WMT)(pThread->pThreadData);*/ + return wait_event_interruptible(pEvent->waitQueue, + (/*!RB_EMPTY(&pDevWmt->rActiveOpQ) ||*/ osal_thread_should_stop(pThread) || (*pChecker)(pThread))); + } + return -1; +} + +_osal_inline_ INT32 +osal_thread_destroy ( + P_OSAL_THREAD pThread + ) +{ + if (pThread && (pThread->pThread)) { + kthread_stop(pThread->pThread); + pThread->pThread = NULL; + } + return 0; +} + +/* + *OSAL layer Signal Opeartion releated APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +_osal_inline_ INT32 +osal_signal_init ( + P_OSAL_SIGNAL pSignal + ) +{ + if (pSignal) { + init_completion(&pSignal->comp); + return 0; + } + else { + return -1; + } +} + +_osal_inline_ INT32 +osal_wait_for_signal ( + P_OSAL_SIGNAL pSignal + ) +{ + if (pSignal) { + wait_for_completion_interruptible(&pSignal->comp); + return 0; + } + else { + return -1; + } +} + +_osal_inline_ INT32 +osal_wait_for_signal_timeout ( + P_OSAL_SIGNAL pSignal + ) +{ + /* return wait_for_completion_interruptible_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue));*/ + /* [ChangeFeature][George] gps driver may be closed by -ERESTARTSYS. + * Avoid using *interruptible" version in order to complete our jobs, such + * as function off gracefully. + */ + return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); +} + +_osal_inline_ INT32 +osal_raise_signal ( + P_OSAL_SIGNAL pSignal + ) +{ + // TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! + complete(&pSignal->comp); + return 0; +} + +_osal_inline_ INT32 +osal_signal_deinit ( + P_OSAL_SIGNAL pSignal + ) +{ + // TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! + pSignal->timeoutValue = 0; + return 0; +} + + +/* + *OSAL layer Event Opeartion releated APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +INT32 osal_event_init ( + P_OSAL_EVENT pEvent + ) +{ + init_waitqueue_head(&pEvent->waitQueue); + + return 0; +} + +INT32 osal_wait_for_event( + P_OSAL_EVENT pEvent, + INT32 (*condition)(PVOID), + void *cond_pa + ) +{ + return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa)); +} + +INT32 osal_wait_for_event_timeout( + P_OSAL_EVENT pEvent, + INT32 (*condition)(PVOID), + void *cond_pa + ) +{ + return wait_event_interruptible_timeout(pEvent->waitQueue, condition(cond_pa), msecs_to_jiffies(pEvent->timeoutValue)); +} + +INT32 osal_trigger_event( + P_OSAL_EVENT pEvent + ) +{ + INT32 ret = 0; + wake_up_interruptible(&pEvent->waitQueue); + return ret; +} + +INT32 +osal_event_deinit ( + P_OSAL_EVENT pEvent + ) +{ + return 0; +} + +_osal_inline_ LONG osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset) +{ + UINT32 ms = pEvent->timeoutValue; + if (ms != 0) + { + return wait_event_interruptible_timeout(pEvent->waitQueue, test_bit(bitOffset, pState), msecs_to_jiffies(ms)); + } + else + { + return wait_event_interruptible(pEvent->waitQueue, test_bit(bitOffset, pState)); + } + +} + +_osal_inline_ LONG osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset) +{ + UINT32 ms = pEvent->timeoutValue; + if (ms != 0) + { + return wait_event_interruptible_timeout(pEvent->waitQueue, !test_bit(bitOffset, pState), msecs_to_jiffies(ms)); + } + else + { + return wait_event_interruptible(pEvent->waitQueue, !test_bit(bitOffset, pState)); + } + +} + +/* + *bit test and set/clear operations APIs + * + * +*/ +#if OS_BIT_OPS_SUPPORT +#define osal_bit_op_lock(x) +#define osal_bit_op_unlock(x) +#else + +_osal_inline_ INT32 osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} + +_osal_inline_ INT32 osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} +#endif +_osal_inline_ INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + osal_bit_op_lock(&(pData->opLock)); + clear_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return 0; +} + +_osal_inline_ INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + osal_bit_op_lock(&(pData->opLock)); + set_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return 0; +} + +_osal_inline_ INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + osal_bit_op_lock(&(pData->opLock)); + iRet = test_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; +} + +_osal_inline_ INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + osal_bit_op_lock(&(pData->opLock)); + iRet = test_and_clear_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; + +} + +_osal_inline_ INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + osal_bit_op_lock(&(pData->opLock)); + iRet = test_and_set_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; +} + + +/* + *tiemr operations APIs + *create + *stop + * modify + *create + *delete + * +*/ + +INT32 osal_timer_create(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + init_timer(timer); + timer->function = pTimer->timeoutHandler; + timer->data = (ULONG)pTimer->timeroutHandlerData; + return 0; +} +INT32 osal_timer_start(P_OSAL_TIMER pTimer, UINT32 ms) +{ + + struct timer_list *timer = &pTimer->timer; + timer->expires = jiffies + (ms/(1000/HZ)); + add_timer(timer); + return 0; +} + +INT32 osal_timer_stop(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + del_timer(timer); + return 0; +} + +INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + del_timer_sync(timer); + return 0; +} + +INT32 osal_timer_modify(P_OSAL_TIMER pTimer, UINT32 ms) +{ + + mod_timer(&pTimer->timer, jiffies + (ms)/(1000/HZ)); + return 0; +} + +INT32 _osal_fifo_init(OSAL_FIFO *pFifo, UINT8 *buf, UINT32 size) +{ + struct kfifo *fifo = NULL; + INT32 ret = -1; + + if(!pFifo || pFifo->pFifoBody) + { + printk (KERN_ERR "pFifo must be !NULL, pFifo->pFifoBody must be NULL\n"); + printk (KERN_ERR "pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", pFifo, pFifo->pFifoBody); + return -1; + } + + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + spin_lock_init(&pFifo->fifoSpinlock); + fifo = kfifo_alloc(size, /*GFP_KERNEL*/GFP_ATOMIC, &pFifo->fifoSpinlock); + if (NULL == fifo) + { + ret = -2; + }else + { + ret = 0; + } + #else + fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (!buf){ + /*fifo's buffer is not ready, we allocate automatically*/ + ret = kfifo_alloc(fifo, size, /*GFP_KERNEL*/GFP_ATOMIC); + }else + { + if(is_power_of_2(size)) + { + kfifo_init(fifo, buf, size); + ret = 0; + } + else + { + kfifo_free(fifo); + fifo = NULL; + ret = -1; + } + } + #endif + pFifo->pFifoBody = fifo; + return (ret < 0) ? (-1) : (0); +} + +INT32 _osal_fifo_deinit(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + kfifo_free(fifo); + + } + + return 0; +} + +INT32 _osal_fifo_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + ret = fifo->size; + #else + ret = kfifo_size(fifo); + #endif + + } + + return ret; +} + +/*returns unused bytes in fifo*/ +INT32 _osal_fifo_avail_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + ret = fifo->size - kfifo_len(fifo); + #else + ret = kfifo_avail(fifo); + #endif + } + + return ret; +} + +/*returns used bytes in fifo*/ +INT32 _osal_fifo_len(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + ret = kfifo_len(fifo); + } + + return ret; +} + +INT32 _osal_fifo_is_empty(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + ret = (fifo->in == fifo->out); + #else + ret = kfifo_is_empty(fifo); + #endif + } + + return ret; +} + +INT32 _osal_fifo_is_full(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + ret = (fifo->size == _osal_fifo_len(pFifo)); + #else + ret = kfifo_is_full(fifo); + #endif + } + + return ret; +} + +INT32 _osal_fifo_data_in(OSAL_FIFO *pFifo, const VOID *buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + ret = kfifo_put(fifo, buf, len); + #else + ret = kfifo_in(fifo, buf, len); + #endif + + } + else + { + printk("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n", + __func__, len, _osal_fifo_avail_size(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_data_out(OSAL_FIFO *pFifo, void *buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo && buf && (len <= _osal_fifo_len(pFifo))) + { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + ret = kfifo_get(fifo, buf, len); + #else + ret = kfifo_out(fifo, buf, len); + #endif + } + else + { + printk("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n", + __func__, len, _osal_fifo_len(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_reset(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if(!pFifo || !pFifo->pFifoBody) + { + printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if(fifo) + { + kfifo_reset(fifo); + } + + return 0; +} + +INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size) +{ + if(!pFifo) + { + printk("%s:pFifo = NULL, error\n", __func__); + return -1; + } + + pFifo->FifoInit = _osal_fifo_init; + pFifo->FifoDeInit = _osal_fifo_deinit; + pFifo->FifoSz = _osal_fifo_size; + pFifo->FifoAvailSz = _osal_fifo_avail_size; + pFifo->FifoLen = _osal_fifo_len; + pFifo->FifoIsEmpty = _osal_fifo_is_empty; + pFifo->FifoIsFull = _osal_fifo_is_full; + pFifo->FifoDataIn = _osal_fifo_data_in; + pFifo->FifoDataOut = _osal_fifo_data_out; + pFifo->FifoReset = _osal_fifo_reset; + + if(NULL != pFifo->pFifoBody) + { + printk("%s:Becasue pFifo room is avialable, we clear the room and allocate them again.\n", __func__); + pFifo->FifoDeInit(pFifo->pFifoBody); + pFifo->pFifoBody = NULL; + } + + pFifo->FifoInit(pFifo, buffer, size); + + return 0; +} + +VOID osal_fifo_deinit(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + pFifo->FifoDeInit(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + +#else + + if(pFifo->pFifoBody) + { + kfree(pFifo->pFifoBody); + } +#endif +} + +INT32 osal_fifo_reset(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoReset(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return -1; + } +} + +UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + if(pFifo) + { + return pFifo->FifoDataIn(pFifo, buffer, size); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + if(pFifo) + { + return pFifo->FifoDataOut(pFifo, buffer, size); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_len(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoLen(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoSz(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoAvailSz(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoIsEmpty(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo) +{ + if(pFifo) + { + return pFifo->FifoIsFull(pFifo); + } + else + { + printk("%s:pFifo = NULL, error\n", __func__); + return 0; + } +} + +INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK pLock) +{ + if(!pLock) + { + return -1; + } + else + { + wake_lock_init(&pLock->wake_lock, WAKE_LOCK_SUSPEND, pLock->name); + + return 0; + } +} + +INT32 osal_wake_lock(P_OSAL_WAKE_LOCK pLock) +{ + if(!pLock) + { + return -1; + } + else + { + wake_lock(&pLock->wake_lock); + + return 0; + } +} + + +INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK pLock) +{ + if(!pLock) + { + return -1; + } + else + { + wake_unlock(&pLock->wake_lock); + + return 0; + } +} + +INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK pLock) +{ + INT32 count = 0; + + if(!pLock) + { + return -1; + } + else + { + count = wake_lock_active(&pLock->wake_lock); + return count; + } +} + +/* + *sleepable lock operations APIs + *init + *lock + *unlock + *destroy + * +*/ + +#if !defined(CONFIG_PROVE_LOCKING) +INT32 osal_unsleepable_lock_init (P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_init(&(pUSL->lock)); + return 0; +} +#endif + +INT32 osal_lock_unsleepable_lock (P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} +INT32 osal_unlock_unsleepable_lock (P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + +extern INT32 osal_unsleepable_lock_deinit (P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + return 0; +} + +/* + *unsleepable operations APIs + *init + *lock + *unlock + *destroy + + * +*/ + +#if !defined(CONFIG_PROVE_LOCKING) +INT32 osal_sleepable_lock_init (P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_init (&pSL->lock); + return 0; +} +#endif + +INT32 osal_lock_sleepable_lock (P_OSAL_SLEEPABLE_LOCK pSL) +{ + return mutex_lock_killable(&pSL->lock); +} + +INT32 osal_unlock_sleepable_lock (P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_unlock(&pSL->lock); + return 0; +} + + +INT32 osal_sleepable_lock_deinit (P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_destroy (&pSL->lock); + return 0; +} + +INT32 osal_msleep(UINT32 ms) +{ + msleep(ms); + return 0; +} + +INT32 osal_gettimeofday(PINT32 sec, PINT32 usec) +{ + INT32 ret = 0; + struct timeval now; + + do_gettimeofday(&now); + + if(sec != NULL) + *sec = now.tv_sec; + else + ret = -1; + + if(usec != NULL) + *usec = now.tv_usec; + else + ret = -1; + + return ret; +} + +INT32 osal_printtimeofday(const PUINT8 prefix) +{ + INT32 ret; + INT32 sec; + INT32 usec; + + ret = osal_gettimeofday(&sec, &usec); + ret += osal_dbg_print("%s>sec=%d, usec=%d\n",prefix, sec, usec); + + return ret; +} + +VOID +osal_buffer_dump ( + const UINT8 *buf, + const UINT8 *title, + const UINT32 len, + const UINT32 limit + ) +{ + INT32 k; + UINT32 dump_len; + + printk("start of dump>[%s] len=%d, limit=%d,", title, len, limit); + + dump_len = ((0 != limit) && (len > limit)) ? limit : len; +#if 0 + if(limit != 0) + { + len = (len > limit)? (limit) : (len); + } +#endif + + for (k = 0; k < dump_len ; k++) { + if((k != 0) && ( k % 16 == 0)) printk("\n"); + printk("0x%02x ", buf[k]); + } + printk("op.opId : 0xFFFFFFFF; +} + +MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp) +{ + return (pOp && pOp->signal.timeoutValue) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} + +VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result) +{ + if (pOp) + { + pOp->result = result; + osal_raise_signal(&pOp->signal); + } +} + diff --git a/drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c new file mode 100755 index 000000000000..17037da3623c --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c @@ -0,0 +1,514 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stp_exp.h" +#include "wmt_exp.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +#define BT_DRIVER_NAME "mtk_stp_BT_chrdev" +#define BT_DEV_MAJOR 192 // never used number + +#define PFX "[MTK-BT] " +#define BT_LOG_DBG 3 +#define BT_LOG_INFO 2 +#define BT_LOG_WARN 1 +#define BT_LOG_ERR 0 + +#define COMBO_IOC_BT_HWVER 6 + +#define COMBO_IOC_MAGIC 0xb0 +#define COMBO_IOCTL_FW_ASSERT _IOWR(COMBO_IOC_MAGIC, 0, void*) + +unsigned int gDbgLevel = BT_LOG_INFO; + +#define BT_DBG_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_DBG){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define BT_INFO_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_INFO){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define BT_WARN_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_WARN){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define BT_ERR_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_ERR){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define BT_TRC_FUNC(f) if(gDbgLevel >= BT_LOG_DBG){printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);} + +#define VERSION "1.0" +#define BT_NVRAM_CUSTOM_NAME "/data/BT_Addr" + +static int BT_devs = 1; /* device count */ +static int BT_major = BT_DEV_MAJOR; /* dynamic allocation */ +module_param(BT_major, uint, 0); +static struct cdev BT_cdev; + +static unsigned char i_buf[MTKSTP_BUFFER_SIZE]; // input buffer of read() +static unsigned char o_buf[MTKSTP_BUFFER_SIZE]; // output buffer of write() +static struct semaphore wr_mtx, rd_mtx; +static wait_queue_head_t inq; /* read queues */ +static DECLARE_WAIT_QUEUE_HEAD(BT_wq); +static int flag = 0; +volatile int retflag = 0; + +unsigned char g_bt_bd_addr[10]={0x01,0x1a,0xfc,0x06,0x00,0x55,0x66,0x77,0x88,0x00}; +unsigned char g_nvram_btdata[8]; + +static int nvram_read(char *filename, char *buf, ssize_t len, int offset) +{ + struct file *fd; + //ssize_t ret; + int retLen = -1; + + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + fd = filp_open(filename, O_WRONLY|O_CREAT, 0644); + + if(IS_ERR(fd)) { + BT_ERR_FUNC("failed to open!!\n"); + return -1; + } + do{ + if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) + { + BT_ERR_FUNC("file can not be read!!\n"); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if(fd->f_op->llseek(fd, offset, 0) != offset) { + BT_ERR_FUNC("[nvram_read] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + + retLen = fd->f_op->read(fd, + buf, + len, + &fd->f_pos); + + }while(false); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; +} + + +int platform_load_nvram_data( char * filename, char * buf, int len) +{ + //int ret; + BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n"); + + return nvram_read( filename, buf, len, 0); +} + +static void bt_cdev_rst_cb( + ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, + ENUM_WMTMSG_TYPE_T type, + void *buf, + unsigned int sz){ + + /* + To handle reset procedure please + */ + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + BT_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %d\n", sizeof(ENUM_WMTRSTMSG_TYPE_T)); + if(sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)){ + memcpy((char *)&rst_msg, (char *)buf, sz); + BT_INFO_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + if((src == WMTDRV_TYPE_WMT) && + (dst == WMTDRV_TYPE_BT) && + (type == WMTMSG_TYPE_RESET)){ + if(rst_msg == WMTRSTMSG_RESET_START){ + BT_INFO_FUNC("BT restart start!\n"); + retflag = 1; + wake_up_interruptible(&inq); + /*reset_start message handling*/ + + } else if(rst_msg == WMTRSTMSG_RESET_END){ + BT_INFO_FUNC("BT restart end!\n"); + retflag = 2; + wake_up_interruptible(&inq); + /*reset_end message handling*/ + } + } + } else { + /*message format invalid*/ + BT_INFO_FUNC("message format invalid!\n"); + } +} + +void BT_event_cb(void) +{ + BT_DBG_FUNC("BT_event_cb() \n"); + + flag = 1; + wake_up(&BT_wq); + + /* finally, awake any reader */ + wake_up_interruptible(&inq); /* blocked in read() and select() */ + + return; +} + +unsigned int BT_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + +// down(&wr_mtx); + /* + * The buffer is circular; it is considered full + * if "wp" is right behind "rp". "left" is 0 if the + * buffer is empty, and it is "1" if it is completely full. + */ + if (mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) + { + poll_wait(filp, &inq, wait); + + /* empty let select sleep */ + if((!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) || retflag) + { + mask |= POLLIN | POLLRDNORM; /* readable */ + } + } + else + { + mask |= POLLIN | POLLRDNORM; /* readable */ + } + + /* do we need condition? */ + mask |= POLLOUT | POLLWRNORM; /* writable */ +// up(&wr_mtx); + return mask; +} + + +ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + int retval = 0; + int written = 0; + down(&wr_mtx); + + BT_DBG_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos); + if(retflag) + { + if (retflag == 1) //reset start + { + retval = -88; + BT_INFO_FUNC("MT662x reset Write: start\n"); + } + else if (retflag == 2) // reset end + { + retval = -99; + BT_INFO_FUNC("MT662x reset Write: end\n"); + } + goto OUT; + } + + if (count > 0) + { + int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE; + if (copy_from_user(&o_buf[0], &buf[0], copy_size)) + { + retval = -EFAULT; + goto OUT; + } + //printk("%02x ", val); + + written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, BT_TASK_INDX); + if(0 == written) + { + retval = -ENOSPC; + /*no windowspace in STP is available, native process should not call BT_write with no delay at all*/ + BT_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval); + } + else + { + retval = written; + } + + }else + { + retval = -EFAULT; + BT_ERR_FUNC("target packet length:%d is not allowed, retval = %d.\n", count, retval); + } + +OUT: + up(&wr_mtx); + return (retval); +} + +ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + int retval = 0; + + down(&rd_mtx); + + BT_DBG_FUNC("BT_read(): count %d pos %lld\n", count, *f_pos); + if(retflag) + { + if (retflag == 1) //reset start + { + retval = -88; + BT_INFO_FUNC("MT662x reset Read: start\n"); + } + else if (retflag == 2) // reset end + { + retval = -99; + BT_INFO_FUNC("MT662x reset Read: end\n"); + } + goto OUT; + } + + if(count > MTKSTP_BUFFER_SIZE) + { + count = MTKSTP_BUFFER_SIZE; + } + retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); + + while(retval == 0) // got nothing, wait for STP's signal + { + /*If nonblocking mode, return directly O_NONBLOCK is specified during open() */ + if (filp->f_flags & O_NONBLOCK){ + BT_DBG_FUNC("Non-blocking BT_read() \n"); + retval = -EAGAIN; + goto OUT; + } + + BT_DBG_FUNC("BT_read(): wait_event 1\n"); + wait_event(BT_wq, flag != 0); + BT_DBG_FUNC("BT_read(): wait_event 2\n"); + flag = 0; + retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); + BT_DBG_FUNC("BT_read(): mtk_wcn_stp_receive_data() = %d\n", retval); + } + + // we got something from STP driver + if (copy_to_user(buf, i_buf, retval)) + { + retval = -EFAULT; + goto OUT; + } + +OUT: + up(&rd_mtx); + BT_DBG_FUNC("BT_read(): retval = %d\n", retval); + return (retval); +} + +//int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE; + + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + BT_DBG_FUNC("BT_ioctl(): cmd (%d)\n", cmd); + + switch(cmd) + { +#if 0 + case 0: // enable/disable STP + /* George: STP is controlled by WMT only */ + /* mtk_wcn_stp_enable(arg); */ + break; +#endif + case 1: // send raw data + BT_DBG_FUNC("BT_ioctl(): disable raw data from BT dev \n"); + retval = -EINVAL; + break; + case COMBO_IOC_BT_HWVER: + /*get combo hw version*/ + hw_ver_sym = mtk_wcn_wmt_hwver_get(); + + BT_INFO_FUNC("BT_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", hw_ver_sym, sizeof(hw_ver_sym)); + if(copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))){ + retval = -EFAULT; + } + break; + + case COMBO_IOCTL_FW_ASSERT: + /* BT trigger fw assert for debug*/ + BT_INFO_FUNC("BT Set fw assert......\n"); + bRet = mtk_wcn_wmt_assert(); + if (bRet == MTK_WCN_BOOL_TRUE) { + BT_INFO_FUNC("BT Set fw assert OK\n"); + retval = 0; + } else { + BT_INFO_FUNC("BT Set fw assert Failed\n"); + retval = (-1000); + } + break; + + default: + retval = -EFAULT; + BT_DBG_FUNC("BT_ioctl(): unknown cmd (%d)\n", cmd); + break; + } + + return retval; +} + +static int BT_open(struct inode *inode, struct file *file) +{ + BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + if(current->pid ==1) + return 0; +#if 1 /* GeorgeKuo: turn on function before check stp ready */ + /* turn on BT */ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) { + BT_WARN_FUNC("WMT turn on BT fail!\n"); + return -ENODEV; + }else{ + retflag = 0; + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb); + BT_INFO_FUNC("WMT register BT rst cb!\n"); + } +#endif + + if (mtk_wcn_stp_is_ready()) { +#if 0 /* GeorgeKuo: turn on function before check stp ready */ + /* turn on BT */ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) { + BT_WARN_FUNC("WMT turn on BT fail!\n"); + return -ENODEV; + } +#endif + mtk_wcn_stp_set_bluez(0); + + BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n"); + BT_INFO_FUNC("WMT turn on BT OK!\n"); + BT_INFO_FUNC("STP is ready!\n"); + platform_load_nvram_data(BT_NVRAM_CUSTOM_NAME, + (char *)&g_nvram_btdata, sizeof(g_nvram_btdata)); + + BT_INFO_FUNC("Read NVRAM : BD address %02x%02x%02x%02x%02x%02x Cap 0x%02x Codec 0x%02x\n", + g_nvram_btdata[0], g_nvram_btdata[1], g_nvram_btdata[2], + g_nvram_btdata[3], g_nvram_btdata[4], g_nvram_btdata[5], + g_nvram_btdata[6], g_nvram_btdata[7]); + + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb); + BT_INFO_FUNC("mtk_wcn_stp_register_event_cb finish\n"); + } + else { + BT_ERR_FUNC("STP is not ready\n"); + + /*return error code*/ + return -ENODEV; + } + +// init_MUTEX(&wr_mtx); + sema_init(&wr_mtx, 1); +// init_MUTEX(&rd_mtx); + sema_init(&rd_mtx, 1); + BT_INFO_FUNC("finish\n"); + + return 0; +} + +static int BT_close(struct inode *inode, struct file *file) +{ + BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + if(current->pid ==1) + return 0; + retflag = 0; + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) { + BT_INFO_FUNC("WMT turn off BT fail!\n"); + return -EIO; //mostly, native programmer will not check this return value. + } + else { + BT_INFO_FUNC("WMT turn off BT OK!\n"); + } + + return 0; +} + +struct file_operations BT_fops = { + .open = BT_open, + .release = BT_close, + .read = BT_read, + .write = BT_write, +// .ioctl = BT_ioctl, + .unlocked_ioctl = BT_unlocked_ioctl, + .poll = BT_poll +}; + +static int BT_init(void) +{ + dev_t dev = MKDEV(BT_major, 0); + int alloc_ret = 0; + int cdev_err = 0; + + /*static allocate chrdev*/ + alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME); + if (alloc_ret) { + BT_ERR_FUNC("fail to register chrdev\n"); + return alloc_ret; + } + + cdev_init(&BT_cdev, &BT_fops); + BT_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&BT_cdev, dev, BT_devs); + if (cdev_err) + goto error; + + BT_INFO_FUNC("%s driver(major %d) installed.\n", BT_DRIVER_NAME, BT_major); + retflag = 0; + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + + /* init wait queue */ + init_waitqueue_head(&(inq)); + + return 0; + +error: + if (cdev_err == 0) + cdev_del(&BT_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(dev, BT_devs); + + return -1; +} + +static void BT_exit(void) +{ + dev_t dev = MKDEV(BT_major, 0); + retflag = 0; + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); // unregister event callback function + + cdev_del(&BT_cdev); + unregister_chrdev_region(dev, BT_devs); + + BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME); +} + +module_init(BT_init); +module_exit(BT_exit); + + diff --git a/drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c new file mode 100755 index 000000000000..755cd56ed86c --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c @@ -0,0 +1,427 @@ +/** $Log: stp_chrdev_gps.c $ + * + * 12 13 2010 Sean.Wang + * (1) Add GPS_DEBUG_TRACE_GPIO to disable GPIO debugging trace + * (2) Add GPS_DEBUG_DUMP to support GPS data dump + * (3) Add mtk_wcn_stp_is_ready() check in GPS_open() +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stp_exp.h" +#include "wmt_exp.h" + +MODULE_LICENSE("GPL"); + +#define GPS_DRIVER_NAME "mtk_stp_GPS_chrdev" +#define GPS_DEV_MAJOR 191 // never used number +#define GPS_DEBUG_TRACE_GPIO 0 +#define GPS_DEBUG_DUMP 0 + +#define PFX "[GPS] " +#define GPS_LOG_DBG 3 +#define GPS_LOG_INFO 2 +#define GPS_LOG_WARN 1 +#define GPS_LOG_ERR 0 + +#define COMBO_IOC_GPS_HWVER 6 + +unsigned int gDbgLevel = GPS_LOG_DBG; + +#define GPS_DBG_FUNC(fmt, arg...) if(gDbgLevel >= GPS_LOG_DBG){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define GPS_INFO_FUNC(fmt, arg...) if(gDbgLevel >= GPS_LOG_INFO){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define GPS_WARN_FUNC(fmt, arg...) if(gDbgLevel >= GPS_LOG_WARN){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define GPS_ERR_FUNC(fmt, arg...) if(gDbgLevel >= GPS_LOG_ERR){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define GPS_TRC_FUNC(f) if(gDbgLevel >= GPS_LOG_DBG){ printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);} + + +static int GPS_devs = 1; /* device count */ +static int GPS_major = GPS_DEV_MAJOR; /* dynamic allocation */ +module_param(GPS_major, uint, 0); +static struct cdev GPS_cdev; + +static unsigned char i_buf[MTKSTP_BUFFER_SIZE]; // input buffer of read() +static unsigned char o_buf[MTKSTP_BUFFER_SIZE]; // output buffer of write() +static struct semaphore wr_mtx, rd_mtx; +static DECLARE_WAIT_QUEUE_HEAD(GPS_wq); +static int flag = 0; + +static void GPS_event_cb(void); + +ssize_t GPS_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + int retval = 0; + int written = 0; + down(&wr_mtx); + + //GPS_TRC_FUNC(); + + /*printk("%s: count %d pos %lld\n", __func__, count, *f_pos);*/ + if (count > 0) + { + int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE; + if (copy_from_user(&o_buf[0], &buf[0], copy_size)) + { + retval = -EFAULT; + goto out; + } + //printk("%02x ", val); +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_LOW); +#endif + written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, GPS_TASK_INDX); +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_HIGH); +#endif + +#if GPS_DEBUG_DUMP +{ + unsigned char *buf_ptr = &o_buf[0]; + int k=0; + printk("--[GPS-WRITE]--"); + for(k=0; k < 10 ; k++){ + if(k%16 == 0) printk("\n"); + printk("0x%02x ", o_buf[k]); + } + printk("\n"); +} +#endif + /* + If cannot send successfully, enqueue again + + if (written != copy_size) { + // George: FIXME! Move GPS retry handling from app to driver + } + */ + if(0 == written) + { + retval = -ENOSPC; + /*no windowspace in STP is available, native process should not call GPS_write with no delay at all*/ + GPS_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval); + } + else + { + retval = written; + } + } + else + { + retval = -EFAULT; + GPS_ERR_FUNC("target packet length:%d is not allowed, retval = %d.\n", count, retval); + } +out: + up(&wr_mtx); + return (retval); +} + +ssize_t GPS_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + long val = 0; + int retval; + + down(&rd_mtx); + +/* printk("GPS_read(): count %d pos %lld\n", count, *f_pos);*/ + + if(count > MTKSTP_BUFFER_SIZE) + { + count = MTKSTP_BUFFER_SIZE; + } + +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW); +#endif + retval = mtk_wcn_stp_receive_data(i_buf, count, GPS_TASK_INDX); +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_HIGH); +#endif + + while(retval == 0) // got nothing, wait for STP's signal + { + /*wait_event(GPS_wq, flag != 0);*/ /* George: let signal wake up */ + val = wait_event_interruptible(GPS_wq, flag != 0); + flag = 0; + +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW); +#endif + + retval = mtk_wcn_stp_receive_data(i_buf, count, GPS_TASK_INDX); + +#if GPS_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_HIGH); +#endif + /* if we are signaled */ + if (val) { + if (-ERESTARTSYS == val) { + GPS_INFO_FUNC("signaled by -ERESTARTSYS(%ld) \n ", val); + } + else { + GPS_INFO_FUNC("signaled by %ld \n ", val); + } + break; + } + } + +#if GPS_DEBUG_DUMP +{ + unsigned char *buf_ptr = &i_buf[0]; + int k=0; + printk("--[GPS-READ]--"); + for(k=0; k < 10 ; k++){ + if(k%16 == 0) printk("\n"); + printk("0x%02x ", i_buf[k]); + } + printk("--\n"); +} +#endif + + if (retval) { + // we got something from STP driver + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + goto OUT; + } + else { + /* success */ + } + } + else { + // we got nothing from STP driver, being signaled + retval = val; + } + +OUT: + up(&rd_mtx); +/* printk("GPS_read(): retval = %d\n", retval);*/ + return (retval); +} + +//int GPS_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +long GPS_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + + printk("GPS_ioctl(): cmd (%d)\n", cmd); + + switch(cmd) + { + case 0: // enable/disable STP + GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): disable STP control from GPS dev\n"); + retval = -EINVAL; +#if 1 +#else + /* George: STP is controlled by WMT only */ + mtk_wcn_stp_enable(arg); +#endif + break; + + case 1: // send raw data + GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): disable raw data from GPS dev \n"); + retval = -EINVAL; + break; + + case COMBO_IOC_GPS_HWVER: + /*get combo hw version*/ + hw_ver_sym = mtk_wcn_wmt_hwver_get(); + + GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", hw_ver_sym, sizeof(hw_ver_sym)); + if(copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))){ + retval = -EFAULT; + } + break; + + default: + retval = -EFAULT; + GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): unknown cmd (%d)\n", cmd); + break; + } + +/*OUT:*/ + return retval; +} + +static void gps_cdev_rst_cb( + ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, + ENUM_WMTMSG_TYPE_T type, + void *buf, + unsigned int sz){ + + /* + To handle reset procedure please + */ + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + GPS_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %d\n", sizeof(ENUM_WMTRSTMSG_TYPE_T)); + if(sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)){ + memcpy((char *)&rst_msg, (char *)buf, sz); + GPS_INFO_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + if((src==WMTDRV_TYPE_WMT) && + (dst == WMTDRV_TYPE_GPS) && + (type == WMTMSG_TYPE_RESET)){ + if(rst_msg == WMTRSTMSG_RESET_START){ + GPS_INFO_FUNC("gps restart start!\n"); + + /*reset_start message handling*/ + + } else if(rst_msg == WMTRSTMSG_RESET_END){ + GPS_INFO_FUNC("gps restart end!\n"); + + /*reset_end message handling*/ + } + } + } else { + /*message format invalid*/ + } +} + +static int GPS_open(struct inode *inode, struct file *file) +{ + printk("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + if(current->pid ==1) + return 0; + +#if 1 /* GeorgeKuo: turn on function before check stp ready */ + /* turn on BT */ + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS)) { + GPS_WARN_FUNC("WMT turn on GPS fail!\n"); + return -ENODEV; + } else { + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_GPS, gps_cdev_rst_cb); + GPS_INFO_FUNC("WMT turn on GPS OK!\n"); + } +#endif + + if (mtk_wcn_stp_is_ready()) { +#if 0 + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS)) { + GPS_WARN_FUNC("WMT turn on GPS fail!\n"); + return -ENODEV; + } + GPS_INFO_FUNC("WMT turn on GPS OK!\n"); +#endif + mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, GPS_event_cb); + } else { + GPS_ERR_FUNC("STP is not ready, Cannot open GPS Devices\n\r"); + + /*return error code*/ + return -ENODEV; + } + + //init_MUTEX(&wr_mtx); + sema_init(&wr_mtx, 1); + //init_MUTEX(&rd_mtx); + sema_init(&rd_mtx, 1); + + return 0; +} + +static int GPS_close(struct inode *inode, struct file *file) +{ + printk("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + if(current->pid ==1) + return 0; + + /*Flush Rx Queue*/ + mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, 0x0); // unregister event callback function + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_GPS); + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS)) { + GPS_WARN_FUNC("WMT turn off GPS fail!\n"); + return -EIO; //mostly, native programer does not care this return vlaue, but we still return error code. + } + else { + GPS_INFO_FUNC("WMT turn off GPS OK!\n"); + } + + return 0; +} + +struct file_operations GPS_fops = { + .open = GPS_open, + .release = GPS_close, + .read = GPS_read, + .write = GPS_write, +// .ioctl = GPS_ioctl + .unlocked_ioctl = GPS_unlocked_ioctl, +}; + +void GPS_event_cb(void) +{ +/* printk("GPS_event_cb() \n");*/ + + flag = 1; + wake_up(&GPS_wq); + + return; +} + +static int GPS_init(void) +{ + dev_t dev = MKDEV(GPS_major, 0); + int alloc_ret = 0; + int cdev_err = 0; + + /*static allocate chrdev*/ + alloc_ret = register_chrdev_region(dev, 1, GPS_DRIVER_NAME); + if (alloc_ret) { + printk("fail to register chrdev\n"); + return alloc_ret; + } + + cdev_init(&GPS_cdev, &GPS_fops); + GPS_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&GPS_cdev, dev, GPS_devs); + if (cdev_err) + goto error; + + printk(KERN_ALERT "%s driver(major %d) installed.\n", GPS_DRIVER_NAME, GPS_major); + + return 0; + +error: + if (cdev_err == 0) + cdev_del(&GPS_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(dev, GPS_devs); + + return -1; +} + +static void GPS_exit(void) +{ + dev_t dev = MKDEV(GPS_major, 0); + + cdev_del(&GPS_cdev); + unregister_chrdev_region(dev, GPS_devs); + + printk(KERN_ALERT "%s driver removed.\n", GPS_DRIVER_NAME); +} + +module_init(GPS_init); +module_exit(GPS_exit); + +EXPORT_SYMBOL(GPS_event_cb); + diff --git a/drivers/mtk_wcn_combo/common/linux/stp_dbg.c b/drivers/mtk_wcn_combo/common/linux/stp_dbg.c new file mode 100755 index 000000000000..771a4faf3730 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/stp_dbg.c @@ -0,0 +1,1294 @@ +#include // GFP_KERNEL +#include //init_timer, add_time, del_timer_sync +#include //gettimeofday +#include +#include //kzalloc +#include //task's status +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "stp_dbg.h" +//#include "stp_btm.h" +#include "btm_core.h" + +#define PFX_STP_DBG "[STPDbg]" +#define STP_DBG_LOG_LOUD 4 +#define STP_DBG_LOG_DBG 3 +#define STP_DBG_LOG_INFO 2 +#define STP_DBG_LOG_WARN 1 +#define STP_DBG_LOG_ERR 0 + +unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO; +unsigned int gStpDbgLogOut = 0; + +#define STP_DBG_LOUD_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_LOUD){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_DBG_DBG_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_DBG_INFO_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_INFO){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_DBG_WARN_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_WARN){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_DBG_ERR_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_ERR){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);} +#define STP_DBG_TRC_FUNC(f) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "<%s> <%d>\n", __FUNCTION__, __LINE__);} + + +MTKSTP_DBG_T *g_stp_dbg = NULL; + +#define STP_DBG_FAMILY_NAME "STP_DBG" +#define MAX_BIND_PROCESS (4) + +enum { + __STP_DBG_ATTR_INVALID, + STP_DBG_ATTR_MSG, + __STP_DBG_ATTR_MAX, +}; +#define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1) + +enum { + __STP_DBG_COMMAND_INVALID, + STP_DBG_COMMAND_BIND, + STP_DBG_COMMAND_RESET, + __STP_DBG_COMMAND_MAX, +}; +#define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1) + +static struct genl_family stp_dbg_gnl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = STP_DBG_FAMILY_NAME, + .version = 1, + .maxattr = STP_DBG_ATTR_MAX, +}; + +static void stp_dbg_nl_init(void); +static void stp_dbg_nl_deinit(void); +static int stp_dbg_nl_bind( + struct sk_buff *skb, + struct genl_info *info + ); +static int stp_dbg_nl_reset( + struct sk_buff *skb, + struct genl_info *info + ); + +/* attribute policy */ +static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = { + [STP_DBG_ATTR_MSG] = { .type = NLA_NUL_STRING }, +}; + +/* operation definition */ +static struct genl_ops stp_dbg_gnl_ops_bind = { + .cmd = STP_DBG_COMMAND_BIND, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_bind, + .dumpit = NULL, +}; + +static struct genl_ops stp_dbg_gnl_ops_reset = { + .cmd = STP_DBG_COMMAND_RESET, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_reset, + .dumpit = NULL, +}; + +static unsigned int stp_dbg_seqnum = 0; +static int num_bind_process = 0; +static pid_t bind_pid[MAX_BIND_PROCESS]; + +static P_WCN_CORE_DUMP_T g_core_dump = NULL; + +/* core_dump_timeout_handler - handler of coredump timeout + * @ data - core dump object's pointer + * + * No return value + */ +static void core_dump_timeout_handler(ULONG data) +{ + P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T)data; + + STP_DBG_INFO_FUNC(" start\n"); + + stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm); + + STP_DBG_INFO_FUNC(" end\n"); + + if (dmp) { + dmp->sm = CORE_DUMP_TIMEOUT; + } +} + + +/* wcn_core_dump_init - create core dump sys + * @ timeout - core dump time out value + * + * Return object pointer if success, else NULL + */ +P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 timeout) +{ + #define KBYTES (1024*sizeof(char)) + #define L1_BUF_SIZE (32*KBYTES) + #define L2_BUF_SIZE (512*KBYTES) + + P_WCN_CORE_DUMP_T core_dmp = NULL; + + core_dmp = (P_WCN_CORE_DUMP_T)osal_malloc(sizeof(WCN_CORE_DUMP_T)); + if (!core_dmp) { + STP_DBG_ERR_FUNC("alloc mem failed!\n"); + goto fail; + } + + osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T)); + + core_dmp->compressor = wcn_compressor_init("core_dump_compressor", L1_BUF_SIZE, L2_BUF_SIZE); + if (!core_dmp->compressor) { + STP_DBG_ERR_FUNC("create compressor failed!\n"); + goto fail; + } + wcn_compressor_reset(core_dmp->compressor, 1, GZIP); + + core_dmp->dmp_timer.timeoutHandler = core_dump_timeout_handler; + core_dmp->dmp_timer.timeroutHandlerData = (ULONG)core_dmp; + osal_timer_create(&core_dmp->dmp_timer); + core_dmp->timeout = timeout; + + osal_sleepable_lock_init(&core_dmp->dmp_lock); + + core_dmp->sm = CORE_DUMP_INIT; + STP_DBG_INFO_FUNC("create coredump object OK!\n"); + + return core_dmp; + +fail: + if (core_dmp && core_dmp->compressor) { + wcn_compressor_deinit(core_dmp->compressor); + core_dmp->compressor = NULL; + } + + if (core_dmp) { + osal_free(core_dmp); + } + + osal_sleepable_lock_deinit(&core_dmp->dmp_lock); + + return NULL; +} + + +/* wcn_core_dump_deinit - destroy core dump object + * @ dmp - pointer of object + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp) +{ + if (dmp && dmp->compressor) { + wcn_compressor_deinit(dmp->compressor); + dmp->compressor = NULL; + } + + if (dmp) { + osal_sleepable_lock_deinit(&dmp->dmp_lock); + osal_timer_stop(&dmp->dmp_timer); + osal_free(dmp); + } + + return 0; +} + + +static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len) +{ + if (strnstr(buf, "coredump end", len)) { + return 1; + } else { + return 0; + } +} + + +/* wcn_core_dump_in - add a packet to compressor buffer + * @ dmp - pointer of object + * @ buf - input buffer + * @ len - data length + * + * Retunr 0 if success; return 1 if find end string; else error code + */ +INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) +{ + INT32 ret = 0; + INT32 tmp; + #define INFO_HEAD "MT6628 FW CORE, " + + if ((!dmp) || (!buf)) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + switch (dmp->sm) { + case CORE_DUMP_INIT: + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); + + // first package, copy to info buffer + osal_strcpy(&dmp->info[0], INFO_HEAD); + tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD); + tmp = (len > tmp) ? tmp : len; + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp); + dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0'; + + // show coredump start info on UI + //osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start"); + #if WMT_PLAT_ALPS + aee_kernel_dal_show("MT662x coredump start, please wait up to 5 minutes.\n"); + #endif + // parsing data, and check end srting + ret = wcn_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_INFO_FUNC("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + wcn_compressor_in(dmp->compressor, buf, len, 1); + } else { + dmp->sm = CORE_DUMP_DOING; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } + break; + + case CORE_DUMP_DOING: + // parsing data, and check end srting + ret = wcn_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_INFO_FUNC("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + wcn_compressor_in(dmp->compressor, buf, len, 1); + } else { + dmp->sm = CORE_DUMP_DOING; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } + break; + + case CORE_DUMP_DONE: + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); + wcn_compressor_in(dmp->compressor, buf, len, 0); + dmp->sm = CORE_DUMP_DOING; + break; + + case CORE_DUMP_TIMEOUT: + break; + default: + break; + } + + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + + +/* wcn_core_dump_out - get compressed data from compressor buffer + * @ dmp - pointer of object + * @ pbuf - target buffer's pointer + * @ len - data length + * + * Retunr 0 if success; else error code + */ +INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen) +{ + INT32 ret = 0; + + if ((!dmp) || (!pbuf) || (!plen)) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + ret = wcn_compressor_out(dmp->compressor, pbuf, plen); + + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + + +/* wcn_core_dump_reset - reset core dump sys + * @ dmp - pointer of object + * @ timeout - core dump time out value + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout) +{ + if (!dmp) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + dmp->sm = CORE_DUMP_INIT; + dmp->timeout = timeout; + osal_timer_stop(&dmp->dmp_timer); + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1); + + return 0; +} + + +/* wcn_core_dump_flush - Fulsh dump data and reset core dump sys + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_flush(INT32 rst) +{ + PUINT8 pbuf = NULL; + INT32 len = 0; + + if (!g_core_dump) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + wcn_core_dump_out(g_core_dump, &pbuf, &len); + STP_DBG_INFO_FUNC("buf 0x%08x, len %d\n", (unsigned int)pbuf, len); + + // show coredump end info on UI + //osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); + #if WMT_PLAT_ALPS + aee_kernel_dal_show("MT662x coredump end\n"); + + // call AEE driver API + aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info); + #endif + // reset + wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT); + + return 0; +} + + +static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, INT32 finish) +{ + INT32 ret = 0; + z_stream *stream = NULL; + INT32 tmp = *out_sz; + + STP_DBG_INFO_FUNC("in buf 0x%08x, in sz %d\n", (unsigned int)in_buf, in_sz); + STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, tmp); + + stream = (z_stream*)worker; + if (!stream) { + STP_DBG_ERR_FUNC("invalid workspace!\n"); + return -1; + } + + if (in_sz > 0) { + #if 0 + ret = zlib_deflateReset(stream); + if (ret != Z_OK) { + STP_DBG_ERR_FUNC("reset failed!\n"); + return -2; + } + #endif + + stream->next_in = in_buf; + stream->avail_in = in_sz; + stream->next_out = out_buf; + stream->avail_out = tmp; + + zlib_deflate(stream, Z_FULL_FLUSH); + + if (finish) { + while (1) { + int val = zlib_deflate(stream, Z_FINISH); + if (val == Z_OK) { + continue; + } else if (val == Z_STREAM_END) { + break; + } else { + STP_DBG_ERR_FUNC("finish operation failed %d\n", val); + return -3; + } + } + } + + *out_sz = tmp - stream->avail_out; + } + + STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, *out_sz); + + return ret; +} + + +/* wcn_compressor_init - create a compressor and do init + * @ name - compressor's name + * @ L1_buf_sz - L1 buffer size + * @ L2_buf_sz - L2 buffer size + * + * Retunr object's pointer if success, else NULL + */ +P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz) +{ + z_stream *pstream = NULL; + P_WCN_COMPRESSOR_T compress = NULL; + + compress = (P_WCN_COMPRESSOR_T)osal_malloc(sizeof(WCN_COMPRESSOR_T)); + if (!compress) { + STP_DBG_ERR_FUNC("alloc compressor failed!\n"); + goto fail; + } + + osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T)); + osal_memcpy(compress->name, name, STP_OJB_NAME_SZ); + + compress->f_compress_en = 0; + compress->compress_type = GZIP; + + if (compress->compress_type == GZIP) { + compress->worker = osal_malloc(sizeof(z_stream)); + if (!compress->worker) { + STP_DBG_ERR_FUNC("alloc stream failed!\n"); + goto fail; + } + pstream = (z_stream*)compress->worker; + + pstream->workspace = osal_malloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); + if (!pstream->workspace) { + STP_DBG_ERR_FUNC("alloc workspace failed!\n"); + goto fail; + } + zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + + compress->handler = wcn_gzip_compressor; + compress->L1_buf_sz = L1_buf_sz; + compress->L2_buf_sz = L2_buf_sz; + compress->L1_pos = 0; + compress->L2_pos = 0; + compress->uncomp_size = 0; + compress->crc32 = 0xffffffffUL; + + compress->L1_buf = osal_malloc(compress->L1_buf_sz); + if (!compress->L1_buf) { + STP_DBG_ERR_FUNC("alloc %d bytes for L1 buf failed!\n", compress->L1_buf_sz); + goto fail; + } + + compress->L2_buf = osal_malloc(compress->L2_buf_sz); + if (!compress->L2_buf) { + STP_DBG_ERR_FUNC("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz); + goto fail; + } + + STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz); + return compress; + +fail: + if (compress) { + if (compress->L2_buf) { + osal_free(compress->L2_buf); + compress->L2_buf = NULL; + } + + if (compress->L1_buf) { + osal_free(compress->L1_buf); + compress->L1_buf = NULL; + } + + if (compress->worker) { + pstream = (z_stream*)compress->worker; + if ((compress->compress_type == GZIP) && pstream->workspace) { + zlib_deflateEnd(pstream); + osal_free(pstream->workspace); + } + osal_free(compress->worker); + compress->worker = NULL; + } + + if (compress->worker) { + osal_free(compress->worker); + compress->worker = NULL; + } + + osal_free(compress); + compress = NULL; + } + + STP_DBG_ERR_FUNC("init failed!\n"); + + return NULL; +} + + +/* wcn_compressor_deinit - distroy a compressor + * @ cprs - compressor's pointer + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs) +{ + z_stream *pstream = NULL; + + if (cprs) { + if (cprs->L2_buf) { + osal_free(cprs->L2_buf); + cprs->L2_buf = NULL; + } + + if (cprs->L1_buf) { + osal_free(cprs->L1_buf); + cprs->L1_buf = NULL; + } + + if (cprs->worker) { + pstream = (z_stream*)cprs->worker; + if ((cprs->compress_type == GZIP) && pstream->workspace) { + zlib_deflateEnd(pstream); + osal_free(pstream->workspace); + } + osal_free(cprs->worker); + cprs->worker = NULL; + } + + cprs->handler = NULL; + + osal_free(cprs); + } + + STP_DBG_INFO_FUNC("destroy OK\n"); + + return 0; +} + + +/* wcn_compressor_in - put in a raw data, and compress L1 buffer if need + * @ cprs - compressor's pointer + * @ buf - raw data buffer + * @ len - raw data length + * @ finish - core dump finish or not, 1: finished; 0: not finish + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish) +{ + INT32 tmp_len = 0; + INT32 ret = 0; + + if (!cprs) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + + cprs->uncomp_size += len; + + // check L1 buf valid space + if (len > (cprs->L1_buf_sz - cprs->L1_pos)) { + STP_DBG_INFO_FUNC("L1 buffer full\n"); + + if (cprs->f_compress_en && cprs->handler) { + // need compress + // compress L1 buffer, and put result to L2 buffer + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, finish); + if (!ret) { + cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); + cprs->L2_pos += tmp_len; + + if (finish) { + /* Add 8 byte suffix + === + 32 bits UNCOMPRESS SIZE + 32 bits CRC + */ + *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); + *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; + cprs->L2_pos += 8; + } + STP_DBG_INFO_FUNC("compress OK!\n"); + } else { + STP_DBG_ERR_FUNC("compress error!\n"); + } + } else { + // no need compress + // Flush L1 buffer to L2 buffer + STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n"); + + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; + osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); + cprs->L2_pos += tmp_len; + } + + // reset L1 buf pos + cprs->L1_pos = 0; + + // put curren data to L1 buf + if (len > cprs->L1_buf_sz) { + STP_DBG_ERR_FUNC("len=%d, too long err!\n", len); + } else { + STP_DBG_INFO_FUNC("L1 Flushed, and Put %d bytes to L1 buf\n", len); + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + } else { + // put to L1 buffer + STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len); + + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + + return ret; +} + + +/* wcn_compressor_out - get the result data from L2 buffer + * @ cprs - compressor's pointer + * @ pbuf - point to L2 buffer + * @ plen - out len + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen) +{ + INT32 ret = 0; + INT32 tmp_len = 0; + + if ((!cprs) || (!pbuf) || (!plen)) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + + // check if there's L1 data need flush to L2 buffer + if (cprs->L1_pos > 0) { + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + + if (cprs->f_compress_en && cprs->handler) { + // need compress + ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, 1); + + if (!ret) { + cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); + cprs->L2_pos += tmp_len; + + /* Add 8 byte suffix + === + 32 bits UNCOMPRESS SIZE + 32 bits CRC + */ + *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); + *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; + cprs->L2_pos += 8; + + STP_DBG_INFO_FUNC("compress OK!\n"); + } else { + STP_DBG_ERR_FUNC("compress error!\n"); + } + } else { + // no need compress + tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; + osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); + cprs->L2_pos += tmp_len; + } + + cprs->L1_pos = 0; + } + + + *pbuf = cprs->L2_buf; + *plen = cprs->L2_pos; + + STP_DBG_INFO_FUNC("0x%08x, len %d\n", (unsigned int)*pbuf, *plen); + +#if 1 + ret = zlib_deflateReset((z_stream*)cprs->worker); + if (ret != Z_OK) { + STP_DBG_ERR_FUNC("reset failed!\n"); + return -2; + } +#endif + + return 0; +} + + +/* wcn_compressor_reset - reset compressor + * @ cprs - compressor's pointer + * @ enable - enable/disable compress + * @ type - compress algorithm + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type) +{ + if (!cprs) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + + cprs->f_compress_en = enable; + //cprs->f_compress_en = 0; // disable compress for test + cprs->compress_type = type; + cprs->L1_pos = 0; + cprs->L2_pos = 0; + cprs->uncomp_size = 0; + cprs->crc32 = 0xffffffffUL; + + STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type); + + return 0; +} + + +static void stp_dbg_dump_data(unsigned char *pBuf, char * title, int len) +{ + int k = 0; + printk(" %s-len:%d\n", title, len); + //printk(" ", title, len); + for(k=0; k < len ; k++){ + if(k%16 == 0 && k != 0) printk("\n "); + printk("0x%02x ", pBuf[k]); + } + printk("--end\n"); +} + + +static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){ + + unsigned long flags; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + stp_dbg->pkt_trace_no=0; + stp_dbg->is_enable=1; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){ + + unsigned long flags; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + stp_dbg->pkt_trace_no=0; + memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); + stp_dbg->is_enable=0; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){ + + unsigned long flags; + unsigned int internalFlag = stp_dbg->logsys->size < STP_DBG_LOG_ENTRY_NUM; + //#ifdef CONFIG_LOG_STP_INTERNAL + //Here we record log in this circle buffer, if buffer is full , select to overlap earlier log, logic should be okay + internalFlag = 1; + //#endif + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + if(internalFlag){ + stp_dbg->logsys->queue[stp_dbg->logsys->in].id = 0; + stp_dbg->logsys->queue[stp_dbg->logsys->in].len = len; + memset(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), + 0, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len))); + memcpy(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), + buf, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len))); + + stp_dbg->logsys->size++; + stp_dbg->logsys->size = (stp_dbg->logsys->size > STP_DBG_LOG_ENTRY_NUM) ? STP_DBG_LOG_ENTRY_NUM : stp_dbg->logsys->size; + + if (0 != gStpDbgLogOut) + { + STP_DBG_HDR_T *pHdr = NULL; + char* pBuf = NULL; + unsigned int len =0; + pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]); + pBuf = (char *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + sizeof (STP_DBG_HDR_T); + len = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof (STP_DBG_HDR_T); + printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \ + pHdr->sec, + pHdr->usec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + gStpDbgType[pHdr->type], + pHdr->no, + pHdr->len, + pHdr->seq, + pHdr->ack + + ); + if (0 < len){ + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len); + } + + } + stp_dbg->logsys->in = (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->in + 1); + STP_DBG_DBG_FUNC("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in); + } else { + STP_DBG_WARN_FUNC("logsys FULL!\n"); + } + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg){ + int retval = 0; +//#ifndef CONFIG_LOG_STP_INTERNAL + + if(stp_dbg->btm != NULL){ + retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *)stp_dbg->btm); + } + +//#endif + + return retval; +} + +int stp_dbg_log_ctrl (unsigned int on) +{ + if (on != 0) + { + gStpDbgLogOut = 1; + printk ("STP-DBG: enable pkt log dump out.\n"); + } + else + { + gStpDbgLogOut = 0; + printk ("STP-DBG: disable pkt log dump out.\n"); + } + return 0; +} + +int stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){ + return _stp_dbg_dmp_in(stp_dbg, buf, len); +} + + +int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg) +{ + #define MAX_DMP_NUM 80 + unsigned long flags; + char *pBuf = NULL; + int len = 0; + STP_DBG_HDR_T *pHdr = NULL; + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + //Not to dequeue from loging system + inIndex = stp_dbg->logsys->in; + dumpSize = stp_dbg->logsys->size; + if (STP_DBG_LOG_ENTRY_NUM == dumpSize) + { + outIndex = inIndex; + } + else + { + outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM; + } + + if (dumpSize > MAX_DMP_NUM) + { + + outIndex += (dumpSize - MAX_DMP_NUM); + outIndex %= STP_DBG_LOG_ENTRY_NUM; + dumpSize = MAX_DMP_NUM; + + } + STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while(dumpSize > 0){ + pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[outIndex].buffer[0]); + pBuf = &(stp_dbg->logsys->queue[outIndex].buffer[0]) + sizeof (STP_DBG_HDR_T); + len = stp_dbg->logsys->queue[outIndex].len - sizeof (STP_DBG_HDR_T); + len = len > STP_PKT_SZ ? STP_PKT_SZ : len; + printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \ + pHdr->sec, + pHdr->usec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + gStpDbgType[pHdr->type], + pHdr->no, + pHdr->len, + pHdr->seq, + pHdr->ack + ); + + + if (0 < len){ + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len); + } + outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(outIndex + 1); + dumpSize--; + + } + + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +int stp_dbg_dmp_out_ex (char *buf, int *len){ + return stp_dbg_dmp_out(g_stp_dbg, buf, len); +} + +int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len){ + + unsigned long flags; + int remaining = 0; + *len = 0; + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + if(stp_dbg->logsys->size > 0){ + memcpy(buf, &(stp_dbg->logsys->queue[stp_dbg->logsys->out].buffer[0]), + stp_dbg->logsys->queue[stp_dbg->logsys->out].len); + + (*len) = stp_dbg->logsys->queue[stp_dbg->logsys->out].len; + stp_dbg->logsys->out = (stp_dbg->logsys->out >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->out + 1); + stp_dbg->logsys->size--; + + STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out); + } else { + STP_DBG_LOUD_FUNC("logsys EMPTY!\n"); + } + + remaining = (stp_dbg->logsys->size == 0)?(0):(1); + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return remaining; +} + +static int stp_dbg_fill_hdr(struct stp_dbg_pkt_hdr *hdr, int type, int ack, int seq, int crc, int dir, int len, int dbg_type){ + + struct timeval now; + + if(!hdr){ + STP_DBG_ERR_FUNC("function invalid\n"); + return -EINVAL; + } else { + do_gettimeofday(&now); + hdr->dbg_type = dbg_type; + hdr->ack = ack; + hdr->seq = seq; + hdr->sec = now.tv_sec; + hdr->usec = now.tv_usec; + hdr->crc = crc; + hdr->dir = dir;//rx + hdr->dmy = 0xffffffff; + hdr->len = len; + hdr->type = type; + return 0; + } +} + +static int +stp_dbg_add_pkt ( + MTKSTP_DBG_T*stp_dbg, + struct stp_dbg_pkt_hdr *hdr, + const unsigned char *body + ) +{ + //fix the frame size large issues. + static struct stp_dbg_pkt stp_pkt; + uint32_t hdr_sz = sizeof(struct stp_dbg_pkt_hdr); + uint32_t body_sz = 0; + + osal_bug_on(!stp_dbg); + + if(hdr->dbg_type == STP_DBG_PKT){ + body_sz = (hdr->len <= STP_PKT_SZ)?(hdr->len):(STP_PKT_SZ); + }else{ + body_sz = (hdr->len <= STP_DMP_SZ)?(hdr->len):(STP_DMP_SZ); + } + + hdr->no = stp_dbg->pkt_trace_no++; + memcpy((uint8_t *)&stp_pkt.hdr, (uint8_t*)hdr, hdr_sz); + if(body != NULL){ + memcpy((uint8_t *)&stp_pkt.raw[0], body, body_sz); + } + _stp_dbg_dmp_in(stp_dbg, (char *) &stp_pkt, hdr_sz + body_sz); + //Only FW DMP MSG should inform BTM-CORE to dump packet to native process + if(hdr->dbg_type == STP_DBG_FW_DMP) + { + stp_gdb_notify_btm_dmp_wq(stp_dbg); + } + + return 0; +} + +int stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, int dbg_type, + int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body) { + + struct stp_dbg_pkt_hdr hdr; + + if (stp_dbg->is_enable == 0) { + /*dbg is disable,and not to log*/ + } + else { + stp_dbg_fill_hdr(&hdr, + (int) type, + (int) ack_no, + (int) seq_no, + (int) crc, + (int) dir, + (int) len, + (int) dbg_type); + + stp_dbg_add_pkt(stp_dbg, &hdr, body); + } + + return 0; +} + +int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){ + return _stp_dbg_enable(stp_dbg); +} + +int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){ + return _stp_dbg_disable(stp_dbg); +} + +static void stp_dbg_nl_init(void) +{ + if(genl_register_family(&stp_dbg_gnl_family) != 0) + { + STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__); + } + else + { + if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0) + { + STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__); + } + + if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0) + { + STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__); + } + } + + return; +} + +static void stp_dbg_nl_deinit(void) +{ + genl_unregister_family(&stp_dbg_gnl_family); + return; +} + +static int stp_dbg_nl_bind( + struct sk_buff *skb, + struct genl_info *info + ) +{ + struct nlattr *na; + char * mydata; + + if (info == NULL) + { + goto out; + } + + STP_DBG_INFO_FUNC("%s():->\n", __func__); + + na = info->attrs[STP_DBG_ATTR_MSG]; + + if (na) + { + mydata = (char *)nla_data(na); + } + + if(num_bind_process < MAX_BIND_PROCESS) + { + bind_pid[num_bind_process] = info->snd_pid; + num_bind_process++; + STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_pid); + } + else + { + STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS); + } + +out: + return 0; +} + +static int stp_dbg_nl_reset( + struct sk_buff *skb, + struct genl_info *info + ) +{ + STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__); + + return 0; +} + +char +stp_dbg_nl_send( + char * aucMsg, + unsigned char cmd + ) +{ + struct sk_buff *skb = NULL; + void *msg_head = NULL; + int rc = -1; + int i; + + if(num_bind_process == 0) + { + /* no listening process */ + STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__); + return 0; + } + + for(i = 0 ; i < num_bind_process ; i++) + { + skb = genlmsg_new(2048, GFP_KERNEL); + + if(skb) + { + msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd); + if(msg_head == NULL) + { + nlmsg_free(skb); + STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__); + return -1; + } + + rc = nla_put_string(skb, STP_DBG_ATTR_MSG, aucMsg); + if(rc != 0) + { + nlmsg_free(skb); + STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__); + return -1; + } + + /* finalize the message */ + genlmsg_end(skb, msg_head); + + /* sending message */ + rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); + if(rc != 0) + { + STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__); + return -1; + } + } + else + { + STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__); + return -1; + } + } + + return 0; +} + + +INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd) +{ + INT32 ret = 0; + + // buffered to compressor + ret = wcn_core_dump_in(g_core_dump, aucMsg, len); + if (ret == 1) { + wcn_core_dump_flush(0); + } + + return ret; +} + + +MTKSTP_DBG_T *stp_dbg_init(void *btm_half){ + + MTKSTP_DBG_T *stp_dbg= NULL; + STP_DBG_INFO_FUNC("stp-dbg init\n"); + + stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL); + if(IS_ERR(stp_dbg)){ + STP_DBG_ERR_FUNC("-ENOMEM\n"); + goto ERR_EXIT1; + } + + stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T)); + if(IS_ERR(stp_dbg->logsys)){ + STP_DBG_ERR_FUNC("-ENOMEM stp_gdb->logsys\n"); + goto ERR_EXIT2; + } + memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); + spin_lock_init(&(stp_dbg->logsys->lock)); + stp_dbg->pkt_trace_no=0; + stp_dbg->is_enable=0; + g_stp_dbg = stp_dbg; + + if(btm_half != NULL){ + stp_dbg->btm = btm_half; + } else { + stp_dbg->btm = NULL; + } + + //bind to netlink + stp_dbg_nl_init(); + + g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT); + + return stp_dbg; + +ERR_EXIT2: + kfree(stp_dbg); + return NULL; + +ERR_EXIT1: + return NULL; +} + +int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg){ + + STP_DBG_INFO_FUNC("stp-dbg deinit\n"); + + wcn_core_dump_deinit(g_core_dump); + + //unbind with netlink + stp_dbg_nl_deinit(); + + if(stp_dbg->logsys){ + vfree(stp_dbg->logsys); + } + + if(stp_dbg){ + kfree(stp_dbg); + } + + return 0; +} + + + + + + + diff --git a/drivers/mtk_wcn_combo/common/linux/stp_uart.c b/drivers/mtk_wcn_combo/common/linux/stp_uart.c new file mode 100755 index 000000000000..0e5b6349c102 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/stp_uart.c @@ -0,0 +1,938 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +#include "stp_exp.h" + +#define N_MTKSTP (15 + 1) /* refer to linux tty.h use N_HCI. */ + +#define HCIUARTSETPROTO _IOW('U', 200, int) + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define PFX "[UART] " +#define UART_LOG_LOUD 4 +#define UART_LOG_DBG 3 +#define UART_LOG_INFO 2 +#define UART_LOG_WARN 1 +#define UART_LOG_ERR 0 + +#define MAX_PACKET_ALLOWED 2000 + + +unsigned int gDbgLevel = UART_LOG_INFO; + +#define UART_DBG_FUNC(fmt, arg...) if(gDbgLevel >= UART_LOG_DBG){ printk(KERN_DEBUG PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define UART_INFO_FUNC(fmt, arg...) if(gDbgLevel >= UART_LOG_INFO){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define UART_WARN_FUNC(fmt, arg...) if(gDbgLevel >= UART_LOG_WARN){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define UART_ERR_FUNC(fmt, arg...) if(gDbgLevel >= UART_LOG_ERR){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define UART_TRC_FUNC(f) if(gDbgLevel >= UART_LOG_DBG){ printk(KERN_DEBUG PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);} + + +#include +#define LDISC_RX_TASKLET 0 +#define LDISC_RX_WORK 1 + +#if WMT_UART_RX_MODE_WORK +#define LDISC_RX LDISC_RX_WORK +#else +#define LDISC_RX LDISC_RX_TASKLET +#endif + +#if (LDISC_RX == LDISC_RX_TASKLET) +#define LDISC_RX_FIFO_SIZE (0x20000) /*8192 bytes*/ +struct kfifo *g_stp_uart_rx_fifo = NULL; +spinlock_t g_stp_uart_rx_fifo_spinlock; +struct tasklet_struct g_stp_uart_rx_fifo_tasklet; +#define RX_BUFFER_LEN 1024 +unsigned char g_rx_data[RX_BUFFER_LEN]; + +//static DEFINE_RWLOCK(g_stp_uart_rx_handling_lock); +#elif (LDISC_RX == LDISC_RX_WORK) + +#define LDISC_RX_FIFO_SIZE (0x4000) /* 16K bytes shall be enough...... */ +#define LDISC_RX_BUF_SIZE (2048) /* 2K bytes in one shot is enough */ + +UINT8 *g_stp_uart_rx_buf; /* for stp rx data parsing */ +struct kfifo *g_stp_uart_rx_fifo = NULL; /* for uart tty data receiving */ +spinlock_t g_stp_uart_rx_fifo_spinlock; /* fifo spinlock */ +struct workqueue_struct *g_stp_uart_rx_wq; /* rx work queue (do not use system_wq) */ +struct work_struct *g_stp_uart_rx_work; /* rx work */ + +#endif + +struct tty_struct *stp_tty = 0x0; + +unsigned char tx_buf[MTKSTP_BUFFER_SIZE] = {0x0}; +int rd_idx = 0; +int wr_idx = 0; +//struct semaphore buf_mtx; +spinlock_t buf_lock; +static INT32 mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size); + + +static inline int stp_uart_tx_wakeup(struct tty_struct *tty) +{ + int len = 0; + int written = 0; + int written_count = 0; + static int i = 0; + //unsigned long flags; + // get data from ring buffer +// down(&buf_mtx); + UART_DBG_FUNC("++\n"); +//// spin_lock_irqsave(&buf_lock, flags); + +#if 0 + if((i > 1000) && (i % 5)== 0) + { + UART_INFO_FUNC("i=(%d), ****** drop data from uart******\n", i); + i++; + return 0; + } else { + + UART_INFO_FUNC("i=(%d)at stp uart **\n", i); + } +#endif + + len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx); + if(len > 0 && len < MAX_PACKET_ALLOWED) + { + i++; + /* + * ops->write is called by the kernel to write a series of + * characters to the tty device. The characters may come from + * user space or kernel space. This routine will return the + * number of characters actually accepted for writing. + */ + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + written = tty->ops->write(tty, &tx_buf[rd_idx], len); + if(written != len) { + UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]tty-ops->write FAIL!len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx); + return -1; + } + written_count = written; + //printk("len = %d, written = %d\n", len, written); + rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE); + // all data is accepted by UART driver, check again in case roll over + len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx); + if(len > 0 && len < MAX_PACKET_ALLOWED) + { + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + written = tty->ops->write(tty, &tx_buf[rd_idx], len); + if (written != len) + { + UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx); + return -1; + } + rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE); + written_count += written; + } + else if(len < 0 || len >= MAX_PACKET_ALLOWED) + { + UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx); + return -1; + } + } + else + { + UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx); + return -1; + } + //up(&buf_mtx); +//// spin_unlock_irqrestore(&buf_lock, flags); + UART_DBG_FUNC("--\n"); + return written_count; +} + +/* ------ LDISC part ------ */ +/* stp_uart_tty_open + * + * Called when line discipline changed to HCI_UART. + * + * Arguments: + * tty pointer to tty info structure + * Return Value: + * 0 if success, otherwise error code + */ +static int stp_uart_tty_open(struct tty_struct *tty) +{ + UART_DBG_FUNC("stp_uart_tty_opentty: %p\n", tty); + + tty->receive_room = 65536; + tty->low_latency = 1; + + /* Flush any pending characters in the driver and line discipline. */ + + /* FIXME: why is this needed. Note don't use ldisc_ref here as the + open path is before the ldisc is referencable */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + /* definition changed!! */ + if (tty->ldisc->ops->flush_buffer) { + tty->ldisc->ops->flush_buffer(tty); + } +#else + if (tty->ldisc.ops->flush_buffer) { + tty->ldisc.ops->flush_buffer(tty); + } +#endif + + tty_driver_flush_buffer(tty); + +// init_MUTEX(&buf_mtx); +//// spin_lock_init(&buf_lock); + + rd_idx = wr_idx = 0; + stp_tty = tty; + mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, mtk_wcn_uart_tx); + + return 0; +} + +/* stp_uart_tty_close() + * + * Called when the line discipline is changed to something + * else, the tty is closed, or the tty detects a hangup. + */ +static void stp_uart_tty_close(struct tty_struct *tty) +{ + UART_DBG_FUNC("stp_uart_tty_close(): tty %p\n", tty); + mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL); + + return; +} + +/* stp_uart_tty_wakeup() + * + * Callback for transmit wakeup. Called when low level + * device driver can accept more send data. + * + * Arguments: tty pointer to associated tty instance data + * Return Value: None + */ +static void stp_uart_tty_wakeup(struct tty_struct *tty) +{ + //printk("%s: start !!\n", __FUNCTION__); + + //clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + + //stp_uart_tx_wakeup(tty); + + return; +} + +/* stp_uart_tty_receive() + * + * Called by tty low level driver when receive data is + * available. + * + * Arguments: tty pointer to tty isntance data + * data pointer to received data + * flags pointer to flags for data + * count count of received data in bytes + * + * Return Value: None + */ +#if (LDISC_RX == LDISC_RX_TASKLET) + +static int stp_uart_fifo_init(void) +{ + int err = 0; + /*add rx fifo*/ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + { + spin_lock_init(&g_stp_uart_rx_fifo_spinlock); + g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_ATOMIC, &g_stp_uart_rx_fifo_spinlock); + if (NULL == g_stp_uart_rx_fifo) + { + UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.35)\n"); + err = -1; + } + } + #else + { + g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (NULL == g_stp_uart_rx_fifo) + { + err = -2; + UART_ERR_FUNC("kzalloc for g_stp_uart_rx_fifo failed (kernel version > 2.6.35)\n"); + } + err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_ATOMIC); + if (0 != err) + { + UART_ERR_FUNC("kfifo_alloc failed, errno(%d)(kernel version > 2.6.35)\n", err); + kfree(g_stp_uart_rx_fifo); + g_stp_uart_rx_fifo = NULL; + err = -3; + } + } + #endif + if (0 == err) + { + if (NULL != g_stp_uart_rx_fifo) + { + kfifo_reset(g_stp_uart_rx_fifo); + UART_ERR_FUNC("stp_uart_fifo_init() success.\n"); + } + else + { + err = -4; + UART_ERR_FUNC("abnormal case, err = 0 but g_stp_uart_rx_fifo = NULL, set err to %d\n", err); + } + } + else + { + UART_ERR_FUNC("stp_uart_fifo_init() failed.\n"); + } + return err; +} + +static int stp_uart_fifo_deinit(void) +{ + if (NULL != g_stp_uart_rx_fifo) + { + kfifo_free(g_stp_uart_rx_fifo); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + //do nothing + #else + kfree(g_stp_uart_rx_fifo); + #endif + g_stp_uart_rx_fifo = NULL; + } + return 0; +} + +static void stp_uart_rx_handling(unsigned long func_data){ + unsigned int how_much_get = 0; + unsigned int how_much_to_get = 0; + unsigned int flag = 0; + +// read_lock(&g_stp_uart_rx_handling_lock); + how_much_to_get = kfifo_len(g_stp_uart_rx_fifo); + + if (how_much_to_get >= RX_BUFFER_LEN) + { + flag = 1; + UART_INFO_FUNC ("fifolen(%d)\n", how_much_to_get); + } + + do{ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + how_much_get= kfifo_get(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN); + #else + how_much_get= kfifo_out(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN); + #endif + //UART_INFO_FUNC ("fifoget(%d)\n", how_much_get); + mtk_wcn_stp_parser_data((UINT8 *)g_rx_data, how_much_get); + how_much_to_get = kfifo_len(g_stp_uart_rx_fifo); + }while(how_much_to_get > 0); + +// read_unlock(&g_stp_uart_rx_handling_lock); + if (1 == flag) + { + UART_INFO_FUNC ("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo)); + } +} + +static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +{ + unsigned int fifo_avail_len = LDISC_RX_FIFO_SIZE - kfifo_len(g_stp_uart_rx_fifo); + unsigned int how_much_put = 0; +#if 0 + { + struct timeval now; + do_gettimeofday(&now); + printk("[+STP][ ][R] %4d --> sec = %lu, --> usec --> %lu\n", + count, now.tv_sec, now.tv_usec); + } +#endif +// write_lock(&g_stp_uart_rx_handling_lock); + if(count > 2000){ + /*this is abnormal*/ + UART_ERR_FUNC("abnormal: buffer count = %d\n", count); + } + /*How much empty seat?*/ + if(fifo_avail_len > 0){ + //UART_INFO_FUNC ("fifo left(%d), count(%d)\n", fifo_avail_len, count); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) + how_much_put = kfifo_put(g_stp_uart_rx_fifo,(unsigned char *) data, count); + #else + how_much_put = kfifo_in(g_stp_uart_rx_fifo,(unsigned char *) data, count); + #endif + + /*schedule it!*/ + tasklet_schedule(&g_stp_uart_rx_fifo_tasklet); + }else{ + UART_ERR_FUNC("stp_uart_tty_receive rxfifo is full!!\n"); + } + +#if 0 + { + struct timeval now; + do_gettimeofday(&now); + printk("[-STP][ ][R] %4d --> sec = %lu, --> usec --> %lu\n", + count, now.tv_sec, now.tv_usec); + } +#endif + +// write_unlock(&g_stp_uart_rx_handling_lock); + +} +#elif (LDISC_RX ==LDISC_RX_WORK) +static int stp_uart_fifo_init(void) +{ + int err = 0; + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + g_stp_uart_rx_buf = vzalloc(LDISC_RX_BUF_SIZE); + if (!g_stp_uart_rx_buf) { + UART_ERR_FUNC("kfifo_alloc failed (kernel version >= 2.6.37)\n"); + err = -4; + goto fifo_init_end; + } + #else + g_stp_uart_rx_buf = vmalloc(LDISC_RX_BUF_SIZE); + if (!g_stp_uart_rx_buf) { + UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.37)\n"); + err = -4; + goto fifo_init_end; + } + memset(g_stp_uart_rx_buf, 0, LDISC_RX_BUF_SIZE); + #endif + + UART_INFO_FUNC("g_stp_uart_rx_buf alloc ok(0x%p, %d)\n", + g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE); + + /*add rx fifo*/ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + spin_lock_init(&g_stp_uart_rx_fifo_spinlock); + g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_KERNEL, &g_stp_uart_rx_fifo_spinlock); + if (NULL == g_stp_uart_rx_fifo) { + UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.33)\n"); + err = -1; + goto fifo_init_end; + } + #else + /* allocate struct kfifo first */ + g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_KERNEL); + if (NULL == g_stp_uart_rx_fifo) { + err = -2; + UART_ERR_FUNC("kzalloc struct kfifo failed (kernel version > 2.6.33)\n"); + goto fifo_init_end; + } + + /* allocate kfifo data buffer then */ + err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_KERNEL); + if (0 != err) { + UART_ERR_FUNC("kfifo_alloc failed, err(%d)(kernel version > 2.6.33)\n", err); + kfree(g_stp_uart_rx_fifo); + g_stp_uart_rx_fifo = NULL; + err = -3; + goto fifo_init_end; + } + #endif + UART_INFO_FUNC("g_stp_uart_rx_fifo alloc ok\n"); + +fifo_init_end: + + if (0 == err) { + /* kfifo init ok */ + kfifo_reset(g_stp_uart_rx_fifo); + UART_DBG_FUNC("g_stp_uart_rx_fifo init success\n"); + } + else { + UART_ERR_FUNC("stp_uart_fifo_init() fail(%d)\n", err); + if (g_stp_uart_rx_buf) { + UART_ERR_FUNC("free g_stp_uart_rx_buf\n"); + vfree(g_stp_uart_rx_buf); + g_stp_uart_rx_buf = NULL; + } + } + + return err; +} + +static int stp_uart_fifo_deinit(void) +{ + if (g_stp_uart_rx_buf) { + vfree(g_stp_uart_rx_buf); + g_stp_uart_rx_buf = NULL; + } + + if (NULL != g_stp_uart_rx_fifo) { + kfifo_free(g_stp_uart_rx_fifo); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + //do nothing + #else + kfree(g_stp_uart_rx_fifo); + #endif + g_stp_uart_rx_fifo = NULL; + } + return 0; +} + +static void stp_uart_fifo_reset (void) { + if (NULL != g_stp_uart_rx_fifo) { + kfifo_reset(g_stp_uart_rx_fifo); + } +} + +static void stp_uart_rx_worker (struct work_struct *work) +{ + unsigned int read; + + if (unlikely(!g_stp_uart_rx_fifo)) { + UART_ERR_FUNC("NULL rx fifo!\n"); + return; + } + if (unlikely(!g_stp_uart_rx_buf)) { + UART_ERR_FUNC("NULL rx buf!\n"); + return; + } + + + /* run until fifo becomes empty */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + while (kfifo_len(g_stp_uart_rx_fifo)) { + read = kfifo_get(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE); + //UART_LOUD_FUNC("kfifo_get(%d)\n", read); + if (likely(read)) { + mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read); + } + } +#else + while (!kfifo_is_empty(g_stp_uart_rx_fifo)) { + read = kfifo_out(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE); + UART_DBG_FUNC("kfifo_out(%d)\n", read); + //printk("rx_work:%d\n\r",read); + if (likely(read)) { + //UART_LOUD_FUNC("->%d\n", read); + mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read); + //UART_LOUD_FUNC("<-\n", read); + } + } +#endif + + return; +} + +/* stp_uart_tty_receive() + * + * Called by tty low level driver when receive data is + * available. + * + * Arguments: tty pointer to tty isntance data + * data pointer to received data + * flags pointer to flags for data + * count count of received data in bytes + * + * Return Value: None + */ +static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +{ + unsigned int written; + + //UART_LOUD_FUNC("URX:%d\n", count); + if (unlikely(count > 2000)) { + UART_WARN_FUNC("abnormal: buffer count = %d\n", count); + } + + if (unlikely(!g_stp_uart_rx_fifo || !g_stp_uart_rx_work || !g_stp_uart_rx_wq)) { + UART_ERR_FUNC("abnormal g_stp_uart_rx_fifo(0x%p),g_stp_uart_rx_work(0x%p),g_stp_uart_rx_wq(0x%p)\n", + g_stp_uart_rx_fifo, g_stp_uart_rx_work, g_stp_uart_rx_wq); + return; + } + + /* need to check available buffer size? skip! */ + + /* need to lock fifo? skip for single writer single reader! */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + written = kfifo_put(g_stp_uart_rx_fifo, (unsigned char *) data, count); +#else + written = kfifo_in(g_stp_uart_rx_fifo, (unsigned char *) data, count); +#endif + //printk("uart_rx:%d,wr:%d\n\r",count,written); + + queue_work(g_stp_uart_rx_wq, g_stp_uart_rx_work); + + if (unlikely(written != count)) { + UART_ERR_FUNC("c(%d),w(%d) bytes dropped\n", count, written); + } + + return; +} + +#else + +static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +{ + +#if 0 + mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_LOW); +#endif + + if(count > 2000){ + /*this is abnormal*/ + UART_ERR_FUNC("stp_uart_tty_receive buffer count = %d\n", count); + } + +#if 0 + { + struct timeval now; + + do_gettimeofday(&now); + + printk("[+STP][ ][R] %4d --> sec = %d, --> usec --> %d\n", + count, now.tv_sec, now.tv_usec); + } +#endif + + + /*There are multi-context to access here? Need to spinlock?*/ + /*Only one context: flush_to_ldisc in tty_buffer.c*/ + mtk_wcn_stp_parser_data((UINT8 *)data, (UINT32)count); + +#if 0 + mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_HIGH); +#endif + + tty_unthrottle(tty); + +#if 0 + { + struct timeval now; + + do_gettimeofday(&now); + + printk("[-STP][ ][R] %4d --> sec = %d, --> usec --> %d\n", + count, now.tv_sec, now.tv_usec); + } +#endif + return; +} +#endif + +/* stp_uart_tty_ioctl() + * + * Process IOCTL system call for the tty device. + * + * Arguments: + * + * tty pointer to tty instance data + * file pointer to open file object for device + * cmd IOCTL command code + * arg argument for IOCTL call (cmd dependent) + * + * Return Value: Command dependent + */ +static int stp_uart_tty_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + + UART_DBG_FUNC("%s =>\n", __FUNCTION__); + + switch (cmd) { + case HCIUARTSETPROTO: + UART_DBG_FUNC(" Set low_latency to TRUE \n"); + tty->low_latency = 1; + break; + default: + UART_DBG_FUNC(" n_tty_ioctl_helper \n"); + err = n_tty_ioctl_helper(tty, file, cmd, arg); + break; + }; + UART_DBG_FUNC("%s <=\n", __FUNCTION__); + + return err; +} + +/* + * We don't provide read/write/poll interface for user space. + */ +static ssize_t stp_uart_tty_read(struct tty_struct *tty, struct file *file, + unsigned char __user *buf, size_t nr) +{ + return 0; +} + +static ssize_t stp_uart_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *data, size_t count) +{ + return 0; +} + +static unsigned int stp_uart_tty_poll(struct tty_struct *tty, + struct file *filp, poll_table *wait) +{ + return 0; +} + +INT32 mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size) +{ + int room; + //int idx = 0; + //unsigned long flags; + unsigned int len; + //static int tmp=0; + static int i = 0; + if(stp_tty == NULL) return -1; + UART_DBG_FUNC("++\n"); + (*written_size) = 0; + + // put data into ring buffer + //down(&buf_mtx); + + + /* + [PatchNeed] + spin_lock_irqsave is redundant + */ + //spin_lock_irqsave(&buf_lock, flags); + + room = (wr_idx >= rd_idx) ? (MTKSTP_BUFFER_SIZE - (wr_idx - rd_idx) - 1) : (rd_idx - wr_idx - 1); + UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx); + /* + [PatchNeed] + Block copy instead of byte copying + */ + if(data == NULL){ + UART_ERR_FUNC("pid(%d)(%s): data is NULL\n", current->pid, current->comm); + (*written_size) = 0; + UART_DBG_FUNC("--\n"); + return -2; + } + + #if 1 + if(unlikely(size > room)){ + UART_ERR_FUNC("pid(%d)(%s)room is not available, size needed(%d), wr_idx(%d), rd_idx(%d), room left(%d)\n", current->pid, current->comm, size, wr_idx, rd_idx, room); + UART_DBG_FUNC("--\n"); + (*written_size) = 0; + return -3; + } + else { + /* + wr_idx : the position next to write + rd_idx : the position next to read + */ + len = min(size, MTKSTP_BUFFER_SIZE - (unsigned int)wr_idx); + memcpy(&tx_buf[wr_idx], &data[0], len); + memcpy(&tx_buf[0], &data[len], size - len); + wr_idx = (wr_idx + size) % MTKSTP_BUFFER_SIZE; + UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx); + i++; + if (size < 0) + { + UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size, wr_idx, rd_idx); + (*written_size) = 0; + } + else if (size == 0) + { + (*written_size) = 0; + } + else if (size < MAX_PACKET_ALLOWED) + { + //only size ~(0, 2000) is allowed + (*written_size) = stp_uart_tx_wakeup(stp_tty); + if(*written_size < 0) + { + //reset read and write index of tx_buffer, is there any risk? + wr_idx = rd_idx = 0; + *written_size = 0; + } + } + else + { + //we filter all packet with size > 2000 + UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size, wr_idx, rd_idx); + (*written_size)= 0; + } + } + #endif + + + #if 0 + while((room > 0) && (size > 0)) + { + tx_buf[wr_idx] = data[idx]; + wr_idx = ((wr_idx + 1) % MTKSTP_BUFFER_SIZE); + idx++; + room--; + size--; + (*written_size)++; + } + #endif + //up(&buf_mtx); + /* + [PatchNeed] + spin_lock_irqsave is redundant + */ +//// spin_lock_irqsave(&buf_lock, flags); + + /*[PatchNeed]To add a tasklet to shedule Uart Tx*/ + UART_DBG_FUNC("--\n"); + return 0; +} + +static int __init mtk_wcn_stp_uart_init(void) +{ + static struct tty_ldisc_ops stp_uart_ldisc; + int err; + int fifo_init_done =0; + + UART_INFO_FUNC("mtk_wcn_stp_uart_init(): MTK STP UART driver\n"); + +#if (LDISC_RX == LDISC_RX_TASKLET) + err = stp_uart_fifo_init(); + if (err != 0) + { + goto init_err; + } + fifo_init_done = 1; + /*init rx tasklet*/ + tasklet_init(&g_stp_uart_rx_fifo_tasklet, stp_uart_rx_handling, (unsigned long) 0); + +#elif (LDISC_RX == LDISC_RX_WORK) + err = stp_uart_fifo_init(); + if (err != 0) { + UART_ERR_FUNC("stp_uart_fifo_init(WORK) error(%d)\n", err); + err = -EFAULT; + goto init_err; + } + fifo_init_done = 1; + + g_stp_uart_rx_work = vmalloc(sizeof(struct work_struct)); + if (!g_stp_uart_rx_work) { + UART_ERR_FUNC("vmalloc work_struct(%d) fail\n", sizeof(struct work_struct)); + err = -ENOMEM; + goto init_err; + } + + g_stp_uart_rx_wq = create_singlethread_workqueue("mtk_urxd"); + if (!g_stp_uart_rx_wq) { + UART_ERR_FUNC("create_singlethread_workqueue fail\n"); + err = -ENOMEM; + goto init_err; + } + + /* init rx work */ + INIT_WORK(g_stp_uart_rx_work, stp_uart_rx_worker); + +#endif + + /* Register the tty discipline */ + memset(&stp_uart_ldisc, 0, sizeof (stp_uart_ldisc)); + stp_uart_ldisc.magic = TTY_LDISC_MAGIC; + stp_uart_ldisc.name = "n_mtkstp"; + stp_uart_ldisc.open = stp_uart_tty_open; + stp_uart_ldisc.close = stp_uart_tty_close; + stp_uart_ldisc.read = stp_uart_tty_read; + stp_uart_ldisc.write = stp_uart_tty_write; + stp_uart_ldisc.ioctl = stp_uart_tty_ioctl; + stp_uart_ldisc.poll = stp_uart_tty_poll; + stp_uart_ldisc.receive_buf = stp_uart_tty_receive; + stp_uart_ldisc.write_wakeup = stp_uart_tty_wakeup; + stp_uart_ldisc.owner = THIS_MODULE; + + if ((err = tty_register_ldisc(N_MTKSTP, &stp_uart_ldisc))) + { + UART_ERR_FUNC("MTK STP line discipline registration failed. (%d)\n", err); + goto init_err; + } + + /* + mtk_wcn_stp_register_if_tx( mtk_wcn_uart_tx); + */ + + return 0; + +init_err: + +#if (LDISC_RX == LDISC_RX_TASKLET) + /* nothing */ + if (fifo_init_done) { + stp_uart_fifo_deinit(); + } +#elif (LDISC_RX == LDISC_RX_WORK) + if (g_stp_uart_rx_wq) { + destroy_workqueue(g_stp_uart_rx_wq); + g_stp_uart_rx_wq = NULL; + } + if (g_stp_uart_rx_work) { + vfree(g_stp_uart_rx_work); + } + if (fifo_init_done) { + stp_uart_fifo_deinit(); + } +#endif + UART_ERR_FUNC("init fail, return(%d)\n", err); + + return err; + +} + +static void __exit mtk_wcn_stp_uart_exit(void) +{ + int err; + + mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL); // unregister if_tx function + + /* Release tty registration of line discipline */ + if ((err = tty_unregister_ldisc(N_MTKSTP))) + { + UART_ERR_FUNC("Can't unregister MTK STP line discipline (%d)\n", err); + } + +#if (LDISC_RX == LDISC_RX_TASKLET) + tasklet_kill(&g_stp_uart_rx_fifo_tasklet); + stp_uart_fifo_deinit(); +#elif (LDISC_RX == LDISC_RX_WORK) + if (g_stp_uart_rx_work) { + cancel_work_sync(g_stp_uart_rx_work); + } + if (g_stp_uart_rx_wq) { + destroy_workqueue(g_stp_uart_rx_wq); + g_stp_uart_rx_wq = NULL; + } + if (g_stp_uart_rx_work) { + vfree(g_stp_uart_rx_work); + g_stp_uart_rx_work = NULL; + } + stp_uart_fifo_deinit(); + +#endif + return; +} + +module_init(mtk_wcn_stp_uart_init); +module_exit(mtk_wcn_stp_uart_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3"); +MODULE_DESCRIPTION("STP-HIF UART Interface"); diff --git a/drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c b/drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c new file mode 100755 index 000000000000..411a2cce4588 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wmt_exp.h" +#include "stp_exp.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +#define WIFI_DRIVER_NAME "mtk_wmt_WIFI_chrdev" +#if WMT_PLAT_APEX +#define WIFI_DEV_MAJOR 194 // never used number +#else +#define WIFI_DEV_MAJOR 153 // never used number +#endif + +#define PFX "[MTK-WIFI] " +#define WIFI_LOG_DBG 3 +#define WIFI_LOG_INFO 2 +#define WIFI_LOG_WARN 1 +#define WIFI_LOG_ERR 0 + + +unsigned int gDbgLevel = WIFI_LOG_INFO; + +#define WIFI_DBG_FUNC(fmt, arg...) if(gDbgLevel >= WIFI_LOG_DBG){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define WIFI_INFO_FUNC(fmt, arg...) if(gDbgLevel >= WIFI_LOG_INFO){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define WIFI_WARN_FUNC(fmt, arg...) if(gDbgLevel >= WIFI_LOG_WARN){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define WIFI_ERR_FUNC(fmt, arg...) if(gDbgLevel >= WIFI_LOG_ERR){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);} +#define WIFI_TRC_FUNC(f) if(gDbgLevel >= WIFI_LOG_DBG){printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);} + +#define VERSION "1.0" + +static int WIFI_devs = 1; /* device count */ +static int WIFI_major = WIFI_DEV_MAJOR; /* dynamic allocation */ +module_param(WIFI_major, uint, 0); +static struct cdev WIFI_cdev; +volatile int retflag = 0; +static struct semaphore wr_mtx; + +static int WIFI_open(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + + return 0; +} + +static int WIFI_close(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, + imajor(inode), + iminor(inode), + current->pid + ); + retflag = 0; + + return 0; +} + +ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + int retval = -EIO; + char local[4] = {0}; + static int opened = 0; + + down(&wr_mtx); + + if (count > 0) { + + if (0 == copy_from_user(local, buf, (count > 4) ? 4 : count)) { + WIFI_INFO_FUNC("WIFI_write %c\n", local[0]); + if (local[0] == '0' && opened == 1) { + //TODO + //Configure the EINT pin to GPIO mode. + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) { + WIFI_INFO_FUNC("WMT turn off WIFI fail!\n"); + } + else { + WIFI_INFO_FUNC("WMT turn off WIFI OK!\n"); + opened = 0; + retval = count; + } + } + else if (local[0] == '1') { + //TODO + //Disable EINT(external interrupt), and set the GPIO to EINT mode. + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { + WIFI_WARN_FUNC("WMT turn on WIFI fail!\n"); + } + else { + opened = 1; + retval = count; + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + } + } + + } + } + + up(&wr_mtx); + return (retval); +} + + +struct file_operations WIFI_fops = { + .open = WIFI_open, + .release = WIFI_close, + .write = WIFI_write, +}; + +static int WIFI_init(void) +{ + dev_t dev = MKDEV(WIFI_major, 0); + int alloc_ret = 0; + int cdev_err = 0; + + /*static allocate chrdev*/ + alloc_ret = register_chrdev_region(dev, 1, WIFI_DRIVER_NAME); + if (alloc_ret) { + WIFI_ERR_FUNC("fail to register chrdev\n"); + return alloc_ret; + } + + cdev_init(&WIFI_cdev, &WIFI_fops); + WIFI_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&WIFI_cdev, dev, WIFI_devs); + if (cdev_err) { + goto error; + } + + sema_init(&wr_mtx, 1); + + WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME, WIFI_major); + retflag = 0; + + return 0; + +error: + if (cdev_err == 0) { + cdev_del(&WIFI_cdev); + } + + if (alloc_ret == 0) { + unregister_chrdev_region(dev, WIFI_devs); + } + + return -1; +} + +static void WIFI_exit(void) +{ + dev_t dev = MKDEV(WIFI_major, 0); + retflag = 0; + + cdev_del(&WIFI_cdev); + unregister_chrdev_region(dev, WIFI_devs); + + WIFI_INFO_FUNC("%s driver removed.\n", WIFI_DRIVER_NAME); +} + +module_init(WIFI_init); +module_exit(WIFI_exit); + diff --git a/drivers/mtk_wcn_combo/common/linux/wmt_dev.c b/drivers/mtk_wcn_combo/common/linux/wmt_dev.c new file mode 100755 index 000000000000..27f792deed9e --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/wmt_dev.c @@ -0,0 +1,1208 @@ +/*! \file + \brief brief description + + Detailed descriptions here. + +*/ + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_dev.h" +#include "wmt_core.h" +#include "wmt_exp.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "wmt_tm.h" +#include "psm_core.h" +#include "stp_core.h" +#include "stp_exp.h" +#include "hif_sdio.h" +#include "wmt_dbg.h" + + +#define MTK_WMT_VERSION "Combo WMT Driver - v1.0" +#define MTK_WMT_DATE "2011/10/04" +#define MTK_COMBO_DRIVER_VERSION "APEX.WCN.MT6620.JB2.MP.V1.0" +#define WMT_DEV_MAJOR 190 // never used number +#define WMT_DEV_NUM 1 + + + +#define WMT_DRIVER_NAME "mtk_stp_wmt" + + +P_OSAL_EVENT gpRxEvent = NULL; + +UINT32 u4RxFlag = 0x0; +static atomic_t gRxCount = ATOMIC_INIT(0); + +/* Linux UCHAR device */ +static int gWmtMajor = WMT_DEV_MAJOR; +static struct cdev gWmtCdev; +static atomic_t gWmtRefCnt = ATOMIC_INIT(0); +/* WMT driver information */ +static UINT8 gLpbkBuf[WMT_LPBK_BUF_LEN] = {0}; //modify for support 1024 loopback +static UINT32 gLpbkBufLog; // George LPBK debug + +P_WMT_PATCH_INFO pPatchInfo = NULL; +UINT32 pAtchNum = 0; + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID wmt_dev_rx_event_cb (VOID) +{ + if (NULL != gpRxEvent) { + u4RxFlag = 1; + atomic_inc(&gRxCount); + wake_up_interruptible(&gpRxEvent->waitQueue); + } + else { + WMT_ERR_FUNC("null gpRxEvent, flush rx!\n"); + wmt_lib_flush_rx(); + } +} + + +INT32 wmt_dev_rx_timeout (P_OSAL_EVENT pEvent) +{ + + UINT32 ms = pEvent->timeoutValue; + LONG lRet = 0; + gpRxEvent = pEvent; + if (0 != ms) + { + lRet = wait_event_interruptible_timeout(gpRxEvent->waitQueue, 0 != u4RxFlag, msecs_to_jiffies(ms)); + } + else + { + lRet = wait_event_interruptible(gpRxEvent->waitQueue, u4RxFlag != 0); + } + u4RxFlag = 0; +// gpRxEvent = NULL; + if (atomic_dec_return(&gRxCount)) { + WMT_ERR_FUNC("gRxCount != 0 (%d), reset it!\n", atomic_read(&gRxCount)); + atomic_set(&gRxCount, 0); + } + + return lRet; +} + +INT32 wmt_dev_read_file ( + UCHAR *pName, + const u8 **ppBufPtr, + INT32 offset, + INT32 padSzBuf + ) +{ + INT32 iRet = -1; + struct file *fd; + //ssize_t iRet; + INT32 file_len; + INT32 read_len; + void *pBuf; + + //struct cred *cred = get_task_cred(current); + const struct cred *cred = get_current_cred(); + + if (!ppBufPtr ) { + WMT_ERR_FUNC("invalid ppBufptr!\n"); + return -1; + } + *ppBufPtr = NULL; + + fd = filp_open(pName, O_RDONLY, 0); + if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { + WMT_ERR_FUNC("failed to open or read!(0x%p, %d, %d)\n", fd, cred->fsuid, cred->fsgid); + return -1; + } + + file_len = fd->f_path.dentry->d_inode->i_size; + pBuf = vmalloc((file_len + BCNT_PATCH_BUF_HEADROOM + 3) & ~0x3UL); + if (!pBuf) { + WMT_ERR_FUNC("failed to vmalloc(%d)\n", (INT32)((file_len + 3) & ~0x3UL)); + goto read_file_done; + } + + do { + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + WMT_ERR_FUNC("failed to seek!!\n"); + goto read_file_done; + } + } + else { + fd->f_pos = offset; + } + } + + read_len = fd->f_op->read(fd, pBuf + padSzBuf, file_len, &fd->f_pos); + if (read_len != file_len) { + WMT_WARN_FUNC("read abnormal: read_len(%d), file_len(%d)\n", read_len, file_len); + } + } while (false); + + iRet = 0; + *ppBufPtr = pBuf; + +read_file_done: + if (iRet) { + if (pBuf) { + vfree(pBuf); + } + } + + filp_close(fd, NULL); + + return (iRet) ? iRet : read_len; +} + +// TODO: [ChangeFeature][George] refine this function name for general filesystem read operation, not patch only. +INT32 wmt_dev_patch_get ( + UCHAR *pPatchName, + osal_firmware **ppPatch, + INT32 padSzBuf + ) +{ + INT32 iRet = -1; + osal_firmware *pfw; + uid_t orig_uid; + gid_t orig_gid; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + //struct cred *cred = get_task_cred(current); + struct cred *cred = (struct cred *)get_current_cred(); +#endif + + mm_segment_t orig_fs = get_fs(); + + if (*ppPatch) { + WMT_WARN_FUNC("f/w patch already exists \n"); + if ((*ppPatch)->data) { + vfree((*ppPatch)->data); + } + kfree(*ppPatch); + *ppPatch = NULL; + } + + if (!osal_strlen(pPatchName)) { + WMT_ERR_FUNC("empty f/w name\n"); + osal_assert((osal_strlen(pPatchName) > 0)); + return -1; + } + + pfw = kzalloc(sizeof(osal_firmware), /*GFP_KERNEL*/GFP_ATOMIC); + if (!pfw) { + WMT_ERR_FUNC("kzalloc(%d) fail\n", sizeof(osal_firmware)); + return -2; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + orig_uid = cred->fsuid; + orig_gid = cred->fsgid; + cred->fsuid = cred->fsgid = 0; +#else + orig_uid = current->fsuid; + orig_gid = current->fsgid; + current->fsuid = current->fsgid = 0; +#endif + + set_fs(get_ds()); + + /* load patch file from fs */ + iRet = wmt_dev_read_file(pPatchName, &pfw->data, 0, padSzBuf); + set_fs(orig_fs); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + cred->fsuid = orig_uid; + cred->fsgid = orig_gid; +#else + current->fsuid = orig_uid; + current->fsgid = orig_gid; +#endif + + if (iRet > 0) { + pfw->size = iRet; + *ppPatch = pfw; + WMT_DBG_FUNC("load (%s) to addr(0x%p) success\n", pPatchName, pfw->data); + return 0; + } + else { + kfree(pfw); + *ppPatch = NULL; + WMT_ERR_FUNC("load file (%s) fail, iRet(%d) \n", pPatchName, iRet); + return -1; + } +} + + +INT32 wmt_dev_patch_put(osal_firmware **ppPatch) +{ + if (NULL != *ppPatch ) { + if ((*ppPatch)->data) { + vfree((*ppPatch)->data); + } + kfree(*ppPatch); + *ppPatch = NULL; + } + return 0; +} + + +VOID wmt_dev_patch_info_free(VOID) +{ + if (pPatchInfo) { + kfree(pPatchInfo); + pPatchInfo = NULL; + } +} + + +MTK_WCN_BOOL wmt_dev_is_file_exist(UCHAR *pFileName) +{ + struct file *fd = NULL; + //ssize_t iRet; + INT32 fileLen = -1; + const struct cred *cred = get_current_cred(); + if(pFileName == NULL) + { + WMT_ERR_FUNC("invalid file name pointer(%p)\n", pFileName); + return MTK_WCN_BOOL_FALSE; + } + if (osal_strlen(pFileName) < osal_strlen(defaultPatchName)) + { + WMT_ERR_FUNC("invalid file name(%s)\n", pFileName); + return MTK_WCN_BOOL_FALSE; + } + + + //struct cred *cred = get_task_cred(current); + + fd = filp_open(pFileName, O_RDONLY, 0); + if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { + WMT_ERR_FUNC("failed to open or read(%s)!(0x%p, %d, %d)\n", pFileName, fd, cred->fsuid, cred->fsgid); + return MTK_WCN_BOOL_FALSE; + } + fileLen = fd->f_path.dentry->d_inode->i_size; + filp_close(fd, NULL); + fd = NULL; + if(fileLen <= 0) + { + WMT_ERR_FUNC("invalid file(%s), length(%d)\n", pFileName, fileLen); + return MTK_WCN_BOOL_FALSE; + } + WMT_ERR_FUNC("valid file(%s), length(%d)\n", pFileName, fileLen); + return true; + +} + +#if defined(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OPEN) +static unsigned long count_last_access_sdio = 0; +static unsigned long count_last_access_uart = 0; +static unsigned long jiffies_last_poll = 0; + +static INT32 wmt_dev_tra_sdio_update(void) +{ + count_last_access_sdio += 1; + //WMT_INFO_FUNC("jiffies_last_access_sdio: jiffies = %ul\n", jiffies); + + return 0; +} + +extern INT32 wmt_dev_tra_uart_update(void) +{ + count_last_access_uart += 1; + //WMT_INFO_FUNC("jiffies_last_access_uart: jiffies = %ul\n", jiffies); + + return 0; +} + +static UINT32 wmt_dev_tra_sdio_poll(void) +{ + #define TIME_THRESHOLD_TO_TEMP_QUERY 3000 + #define COUNT_THRESHOLD_TO_TEMP_QUERY 200 + + unsigned long sdio_during_count = 0; + unsigned long poll_during_time = 0; + + if(jiffies > jiffies_last_poll) + { + poll_during_time = jiffies - jiffies_last_poll; + } + else + { + poll_during_time = 0xffffffff; + } + + WMT_DBG_FUNC("**jiffies_to_mesecs(0xffffffff) = %lu\n", + jiffies_to_msecs(0xffffffff)); + + if(jiffies_to_msecs(poll_during_time) < TIME_THRESHOLD_TO_TEMP_QUERY) + { + WMT_DBG_FUNC("**poll_during_time = %lu < %lu, not to query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY); + return -1; + } + + sdio_during_count = count_last_access_sdio; + + if(sdio_during_count < COUNT_THRESHOLD_TO_TEMP_QUERY) + { + WMT_DBG_FUNC("**sdio_during_count = %lu < %lu, not to query\n", + sdio_during_count, COUNT_THRESHOLD_TO_TEMP_QUERY); + return -1; + } + + count_last_access_sdio = 0; + jiffies_last_poll = jiffies; + + WMT_INFO_FUNC("**poll_during_time = %lu > %lu, sdio_during_count = %lu > %lu, query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY, + jiffies_to_msecs(sdio_during_count) , COUNT_THRESHOLD_TO_TEMP_QUERY); + + return 0; +} + +#if 0 +static UINT32 wmt_dev_tra_uart_poll(void) +{ + //we not support the uart case. + return -1; +} +#endif + +static INT32 wmt_dev_tm_temp_query(void) +{ + #define HISTORY_NUM 5 + #define TEMP_THRESHOLD 65 + #define REFRESH_TIME 300 //sec + + static INT32 temp_table[HISTORY_NUM] = {99}; //not query yet. + static INT32 idx_temp_table = 0; + static struct timeval query_time, now_time; + + INT8 query_cond = 0; + INT32 current_temp = 0; + INT32 index = 0; + + //Query condition 1: + // If we have the high temperature records on the past, we continue to query/monitor + // the real temperature until cooling + for(index = 0; index < HISTORY_NUM ; index++) + { + if(temp_table[index] >= TEMP_THRESHOLD) + { + query_cond = 1; + WMT_INFO_FUNC("high temperature (current temp = %d), we must keep querying temp temperature..\n", temp_table[index]); + } + } + + do_gettimeofday(&now_time); +#if 1 + // Query condition 2: + // Moniter the hif_sdio activity to decide if we have the need to query temperature. + if(!query_cond) + { + if( wmt_dev_tra_sdio_poll()==0) + { + query_cond = 1; + WMT_INFO_FUNC("sdio traffic , we must query temperature..\n"); + } + else + { + WMT_DBG_FUNC("sdio idle traffic ....\n"); + } + + //only WIFI tx power might make temperature varies largely + #if 0 + if(!query_cond) + { + last_access_time = wmt_dev_tra_uart_poll(); + if( jiffies_to_msecs(last_access_time) < TIME_THRESHOLD_TO_TEMP_QUERY) + { + query_cond = 1; + WMT_DBG_FUNC("uart busy traffic , we must query temperature..\n"); + } + else + { + WMT_DBG_FUNC("uart still idle traffic , we don't query temp temperature..\n"); + } + } + #endif + } + #endif + // Query condition 3: + // If the query time exceeds the a certain of period, refresh temp table. + // + if(!query_cond) + { + if( (now_time.tv_sec < query_time.tv_sec) || //time overflow, we refresh temp table again for simplicity! + ((now_time.tv_sec > query_time.tv_sec) && + (now_time.tv_sec - query_time.tv_sec) > REFRESH_TIME)) + { + query_cond = 1; + + WMT_INFO_FUNC("It is long time (> %d sec) not to query, we must query temp temperature..\n", REFRESH_TIME); + for (index = 0; index < HISTORY_NUM ; index++) + { + temp_table[index] = 99; + } + } + } + + if(query_cond) + { + // update the temperature record + mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE); + current_temp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); + mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE); + wmt_lib_notify_stp_sleep(); + idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; + temp_table[idx_temp_table] = current_temp; + do_gettimeofday(&query_time); + + WMT_INFO_FUNC("[Thermal] current_temp = 0x%x \n", (current_temp & 0xFF)); + } + else + { + current_temp = temp_table[idx_temp_table]; + idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; + temp_table[idx_temp_table] = current_temp; + } + + // + // Dump information + // + WMT_DBG_FUNC("[Thermal] idx_temp_table = %d \n", idx_temp_table); + WMT_DBG_FUNC("[Thermal] now.time = %d, query.time = %d, REFRESH_TIME = %d\n", now_time.tv_sec, query_time.tv_sec, REFRESH_TIME); + + WMT_DBG_FUNC("[0] = %d, [1] = %d, [2] = %d, [3] = %d, [4] = %d \n----\n", + temp_table[0], temp_table[1], temp_table[2], temp_table[3], temp_table[4]); + + return current_temp; +} + +static INT32 wmt_dev_tm_temp_set(int temp) +{ + + //TODO: now we no export the APIs to external modules + //This will affect the performance, so we disable the function temporarily. + + return 0; +} + +static INT32 wmt_dev_tm_setup(void) +{ + static struct wmt_thermal_ctrl_ops thermal_ops; + struct wmt_thermal_ctrl_ops *p_thermal_ops = &thermal_ops; + + p_thermal_ops->query_temp = wmt_dev_tm_temp_query; + p_thermal_ops->set_temp = wmt_dev_tm_temp_set; + + wmt_tm_init(p_thermal_ops); + wmt_tm_init_rt(); + + return 0; +} +#else +//STP-UART will access the symbol, so we keep symbol exist even when CONFIG_THERMAL is not support +extern INT32 wmt_dev_tra_uart_update(void) +{ + return 0; +} +#endif + + + +ssize_t +WMT_write ( + struct file *filp, + const char __user *buf, + size_t count, + loff_t *f_pos + ) +{ + INT32 iRet = 0; + UCHAR wrBuf[NAME_MAX+1] = {0}; + INT32 copySize = (count < NAME_MAX) ? count : NAME_MAX; + + WMT_LOUD_FUNC("count:%d copySize:%d\n", count, copySize); + + if (copySize > 0) { + if (copy_from_user(wrBuf, buf, copySize)) { + iRet = -EFAULT; + goto write_done; + } + iRet = copySize; + wrBuf[NAME_MAX] = '\0'; + + if (!strncasecmp(wrBuf, "ok", NAME_MAX)) { + WMT_DBG_FUNC("resp str ok\n"); + //pWmtDevCtx->cmd_result = 0; + wmt_lib_trigger_cmd_signal(0); + } + else { + WMT_WARN_FUNC("warning resp str (%s)\n", wrBuf); + //pWmtDevCtx->cmd_result = -1; + wmt_lib_trigger_cmd_signal(-1); + } + //complete(&pWmtDevCtx->cmd_comp); + + } + +write_done: + return iRet; +} + +ssize_t +WMT_read ( + struct file *filp, + char __user *buf, + size_t count, + loff_t *f_pos + ) +{ + INT32 iRet = 0; + PUCHAR pCmd = NULL; + UINT32 cmdLen = 0; + pCmd = wmt_lib_get_cmd(); + + if (pCmd != NULL) + { + cmdLen = osal_strlen(pCmd) < NAME_MAX ? osal_strlen(pCmd) : NAME_MAX; + WMT_DBG_FUNC("cmd str(%s)\n", pCmd); + if (copy_to_user(buf, pCmd, cmdLen)) { + iRet = -EFAULT; + } + else + { + iRet = cmdLen; + } + } +#if 0 + if (test_and_clear_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) { + iRet = osal_strlen(localBuf) < NAME_MAX ? osal_strlen(localBuf) : NAME_MAX; + // we got something from STP driver + WMT_DBG_FUNC("copy cmd to user by read:%s\n", localBuf); + if (copy_to_user(buf, localBuf, iRet)) { + iRet = -EFAULT; + goto read_done; + } + } +#endif + return iRet; +} + +unsigned int WMT_poll(struct file *filp, poll_table *wait) +{ + UINT32 mask = 0; + P_OSAL_EVENT pEvent = wmt_lib_get_cmd_event(); + + poll_wait(filp, &pEvent->waitQueue, wait); + /* empty let select sleep */ + if (MTK_WCN_BOOL_TRUE == wmt_lib_get_cmd_status()) + { + mask |= POLLIN | POLLRDNORM; /* readable */ + } +#if 0 + if (test_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) { + mask |= POLLIN | POLLRDNORM; /* readable */ + } +#endif + mask |= POLLOUT | POLLWRNORM; /* writable */ + return mask; +} + +//INT32 WMT_ioctl(struct inode *inode, struct file *filp, UINT32 cmd, unsigned long arg) +long +WMT_unlocked_ioctl ( + struct file *filp, + unsigned int cmd, + unsigned long arg + ) +{ +#define WMT_IOC_MAGIC 0xa0 +#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC,4,char*) +#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC,5,int) +#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC,6,int) +#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC,7,int) +#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC,8,char*) +#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC,12,int) +#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC,13,int) +#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC,14,int) +#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC,15,char*) +#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*) +#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*) +#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int) +#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int) +#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int) + + + + INT32 iRet = 0; + UCHAR pBuffer[NAME_MAX + 1]; + WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); + switch(cmd) { + case WMT_IOCTL_SET_PATCH_NAME: /* patch location */ + { + + if (copy_from_user(pBuffer, (void *)arg, NAME_MAX)) { + iRet = -EFAULT; + break; + } + pBuffer[NAME_MAX] = '\0'; + wmt_lib_set_patch_name(pBuffer); + } + break; + + case WMT_IOCTL_SET_STP_MODE: /* stp/hif/fm mode */ + + /* set hif conf */ + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal = NULL; + P_WMT_HIF_CONF pHif = NULL; + + iRet = wmt_lib_set_hif(arg); + if (0 != iRet) + { + WMT_INFO_FUNC("wmt_lib_set_hif fail\n"); + break; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_INFO_FUNC("get_free_lxop fail\n"); + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_HIF_CONF; + + pHif = wmt_lib_get_hif(); + + osal_memcpy(&pOp->op.au4OpData[0], pHif, sizeof(WMT_HIF_CONF)); + pOp->op.u4InfoBit = WMT_OP_HIF_BIT; + pSignal->timeoutValue = 0; + + bRet = wmt_lib_put_act_op(pOp); + WMT_DBG_FUNC("WMT_OPID_HIF_CONF result(%d) \n", bRet); + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + } while (0); + + break; + + case WMT_IOCTL_FUNC_ONOFF_CTRL: /* test turn on/off func */ + + do { + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + if (arg & 0x80000000) + { + bRet = mtk_wcn_wmt_func_on(arg & 0xF); + } + else + { + bRet = mtk_wcn_wmt_func_off(arg & 0xF); + } + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + } while (0); + + break; + + case WMT_IOCTL_LPBK_POWER_CTRL: + /*switch Loopback function on/off + arg: bit0 = 1:turn loopback function on + bit0 = 0:turn loopback function off + */ + do{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + if (arg & 0x01) + { + bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK); + } + else + { + bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); + } + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + }while(0); + + + break; + + + case WMT_IOCTL_LPBK_TEST: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 u4Wait; + //UINT8 lpbk_buf[1024] = {0}; + UINT32 effectiveLen = 0; + P_OSAL_SIGNAL pSignal = NULL; + + if (copy_from_user(&effectiveLen, (void *)arg, sizeof(effectiveLen))) { + iRet = -EFAULT; + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + break; + } + if(effectiveLen > sizeof(gLpbkBuf)) + { + iRet = -EFAULT; + WMT_ERR_FUNC("length is too long\n"); + break; + } + WMT_DBG_FUNC("len = %d\n", effectiveLen); + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail \n"); + iRet = -EFAULT; + break; + } + u4Wait = 2000; + if (copy_from_user(&gLpbkBuf[0], (void *)arg + sizeof(unsigned long), effectiveLen)) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_LPBK; + pOp->op.au4OpData[0] = effectiveLen; //packet length + pOp->op.au4OpData[1] = (UINT32)&gLpbkBuf[0]; //packet buffer pointer + memcpy(&gLpbkBufLog, &gLpbkBuf[((effectiveLen >=4) ? effectiveLen-4:0)], 4); + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", + pOp->op.opId, + pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) buf tail(0x%08x) fail\n", + pOp->op.opId, + pOp->op.au4OpData[0], + gLpbkBufLog); + iRet = -1; + break; + } + else { + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", + pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0] ; + if (copy_to_user((void *)arg + sizeof(ULONG) + sizeof(UCHAR[2048]), gLpbkBuf, iRet)) { + iRet = -EFAULT; + break; + } + } + }while(0); + + break; +#if 0 + case 9: + { + #define LOG_BUF_SZ 300 + UCHAR buf[LOG_BUF_SZ]; + INT32 len = 0; + INT32 remaining = 0; + + remaining = mtk_wcn_stp_btm_get_dmp(buf, &len); + + if(remaining == 0){ + WMT_DBG_FUNC("waiting dmp \n"); + wait_event_interruptible(dmp_wq, dmp_flag != 0); + dmp_flag = 0; + remaining = mtk_wcn_stp_btm_get_dmp(buf, &len); + + //WMT_INFO_FUNC("len = %d ###%s#\n", len, buf); + } else { + WMT_LOUD_FUNC("no waiting dmp \n"); + } + + if(unlikely((len+sizeof(INT32)) >= LOG_BUF_SZ)){ + WMT_ERR_FUNC("len is larger buffer\n"); + iRet = -EFAULT; + goto fail_exit; + } + + buf[sizeof(INT32)+len]='\0'; + + if (copy_to_user((void *)arg, (UCHAR *)&len, sizeof(INT32))){ + iRet = -EFAULT; + goto fail_exit; + } + + if (copy_to_user((void *)arg + sizeof(INT32), buf, len)){ + iRet = -EFAULT; + goto fail_exit; + } + } + break; + + case 10: + { + WMT_INFO_FUNC("Enable combo trace32 dump\n"); + wmt_cdev_t32dmp_enable(); + WMT_INFO_FUNC("Enable STP debugging mode\n"); + mtk_wcn_stp_dbg_enable(); + } + break; + + case 11: + { + WMT_INFO_FUNC("Disable combo trace32 dump\n"); + wmt_cdev_t32dmp_disable(); + WMT_INFO_FUNC("Disable STP debugging mode\n"); + mtk_wcn_stp_dbg_disable(); + } + break; +#endif + + case 10: + { + wmt_lib_host_awake_get(); + mtk_wcn_stp_coredump_start_ctrl(1); + osal_strcpy(pBuffer, "MT662x f/w coredump start-"); + if (copy_from_user(pBuffer + osal_strlen(pBuffer), (void *)arg, NAME_MAX - osal_strlen(pBuffer))) { + //osal_strcpy(pBuffer, "MT662x f/w assert core dump start"); + WMT_ERR_FUNC("copy assert string failed\n"); + } + pBuffer[NAME_MAX] = '\0'; + osal_dbg_assert_aee(pBuffer, pBuffer); + } + break; + case 11: + { + osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); + wmt_lib_host_awake_put(); + } + break; + + + case WMT_IOCTL_GET_CHIP_INFO: + { + if (0 == arg) + { + return wmt_lib_get_icinfo(WMTCHIN_CHIPID); + } + else if (1 == arg) + { + return wmt_lib_get_icinfo(WMTCHIN_HWVER); + } + else if (2 == arg) + { + return wmt_lib_get_icinfo(WMTCHIN_FWVER); + } + } + break; + + case WMT_IOCTL_SET_LAUNCHER_KILL: { + if (1 == arg) { + WMT_INFO_FUNC("launcher may be killed,block abnormal stp tx. \n"); + wmt_lib_set_stp_wmt_last_close(1); + } else { + wmt_lib_set_stp_wmt_last_close(0); + } + + } + break; + + case WMT_IOCTL_SET_PATCH_NUM: { + pAtchNum = arg; + WMT_INFO_FUNC(" get patch num from launcher = %d\n",pAtchNum); + wmt_lib_set_patch_num(pAtchNum); + pPatchInfo = kzalloc(sizeof(WMT_PATCH_INFO)*pAtchNum,GFP_ATOMIC); + if (!pPatchInfo) { + WMT_ERR_FUNC("allocate memory fail!\n"); + break; + } + } + break; + + case WMT_IOCTL_SET_PATCH_INFO: { + WMT_PATCH_INFO wMtPatchInfo; + P_WMT_PATCH_INFO pTemp = NULL; + UINT32 dWloadSeq; + static UINT32 counter = 0; + + if (!pPatchInfo) { + WMT_ERR_FUNC("NULL patch info pointer\n"); + break; + } + + if (copy_from_user(&wMtPatchInfo, (void *)arg, sizeof(WMT_PATCH_INFO))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + dWloadSeq = wMtPatchInfo.dowloadSeq; + WMT_DBG_FUNC("current download seq no is %d,patch name is %s,addres info is 0x%02x,0x%02x,0x%02x,0x%02x\n",dWloadSeq,wMtPatchInfo.patchName,wMtPatchInfo.addRess[0],wMtPatchInfo.addRess[1],wMtPatchInfo.addRess[2],wMtPatchInfo.addRess[3]); + osal_memcpy(pPatchInfo + dWloadSeq - 1,&wMtPatchInfo,sizeof(WMT_PATCH_INFO)); + pTemp = pPatchInfo + dWloadSeq - 1; + if (++counter == pAtchNum) { + wmt_lib_set_patch_info(pPatchInfo); + counter = 0; + } + } + break; + + case WMT_IOCTL_PORT_NAME: { + CHAR cUartName[NAME_MAX + 1]; + if (copy_from_user(cUartName, (void *)arg, NAME_MAX)) { + iRet = -EFAULT; + break; + } + cUartName[NAME_MAX] = '\0'; + wmt_lib_set_uart_name(cUartName); + } + break; + + case WMT_IOCTL_WMT_CFG_NAME: + { + CHAR cWmtCfgName[NAME_MAX + 1]; + if (copy_from_user(cWmtCfgName, (void *)arg, NAME_MAX)) { + iRet = -EFAULT; + break; + } + cWmtCfgName[NAME_MAX] = '\0'; + wmt_conf_set_cfg_file(cWmtCfgName); + } + break; + case WMT_IOCTL_WMT_QUERY_CHIPID: + { + iRet = mtk_wcn_hif_sdio_query_chipid(1); + } + break; + case WMT_IOCTL_WMT_TELL_CHIPID: + { + iRet = mtk_wcn_hif_sdio_tell_chipid(arg); + if (0x6628 == arg) + { + wmt_lib_merge_if_flag_ctrl(1); + } + else + { + wmt_lib_merge_if_flag_ctrl(0); + } + } + break; + case WMT_IOCTL_WMT_COREDUMP_CTRL: + { + if (0 == arg) + { + mtk_wcn_stp_coredump_flag_ctrl(0); + } + else + { + mtk_wcn_stp_coredump_flag_ctrl(1); + } + } + break; + default: + iRet = -EINVAL; + WMT_WARN_FUNC("unknown cmd (%d)\n", cmd); + break; + } + + + return iRet; +} + +static int WMT_open(struct inode *inode, struct file *file) +{ + WMT_INFO_FUNC("major %d minor %d (pid %d)\n", + imajor(inode), + iminor(inode), + current->pid + ); + + if (atomic_inc_return(&gWmtRefCnt) == 1) { + WMT_INFO_FUNC("1st call \n"); + } + + return 0; +} + +static int WMT_close(struct inode *inode, struct file *file) +{ + WMT_INFO_FUNC("major %d minor %d (pid %d)\n", + imajor(inode), + iminor(inode), + current->pid + ); + + if (atomic_dec_return(&gWmtRefCnt) == 0) { + WMT_INFO_FUNC("last call \n"); + } + + return 0; +} + +ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); +ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); +long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + +struct file_operations gWmtFops = { + .open = WMT_open, + .release = WMT_close, + .read = WMT_read, + .write = WMT_write, +// .ioctl = WMT_ioctl, + .unlocked_ioctl = WMT_unlocked_ioctl, + .poll = WMT_poll, +}; + + +static int WMT_init(void) +{ + dev_t devID = MKDEV(gWmtMajor, 0); + INT32 cdevErr = -1; + INT32 ret = -1; + WMT_INFO_FUNC("WMT Version= %s DATE=%s\n" , MTK_WMT_VERSION, MTK_WMT_DATE); + WMT_INFO_FUNC("COMBO Driver Version= %s\n" , MTK_COMBO_DRIVER_VERSION); + /* Prepare a UCHAR device */ + /*static allocate chrdev*/ + + stp_drv_init(); + + ret = register_chrdev_region(devID, WMT_DEV_NUM, WMT_DRIVER_NAME); + if (ret) { + WMT_ERR_FUNC("fail to register chrdev\n"); + return ret; + } + + cdev_init(&gWmtCdev, &gWmtFops); + gWmtCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gWmtCdev, devID, WMT_DEV_NUM); + if (cdevErr) { + WMT_ERR_FUNC("cdev_add() fails (%d) \n", cdevErr); + goto error; + } + WMT_INFO_FUNC("driver(major %d) installed \n", gWmtMajor); + + +#if 0 + pWmtDevCtx = wmt_drv_create(); + if (!pWmtDevCtx) { + WMT_ERR_FUNC("wmt_drv_create() fails \n"); + goto error; + } + + ret = wmt_drv_init(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_init() fails (%d) \n", ret); + goto error; + } + + WMT_INFO_FUNC("stp_btmcb_reg\n"); + wmt_cdev_btmcb_reg(); + + ret = wmt_drv_start(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_start() fails (%d) \n", ret); + goto error; + } +#endif + ret = wmt_lib_init(); + if (ret) { + WMT_ERR_FUNC("wmt_lib_init() fails (%d) \n", ret); + goto error; + } +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_setup(); +#endif + +#if defined(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OPEN) + WMT_INFO_FUNC("wmt_dev_tm_setup\n"); + wmt_dev_tm_setup(); + mtk_wcn_hif_sdio_update_cb_reg(wmt_dev_tra_sdio_update); +#endif + + WMT_INFO_FUNC("success \n"); + return 0; + +error: + wmt_lib_deinit(); +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif + if (cdevErr == 0) { + cdev_del(&gWmtCdev); + } + + if (ret == 0) { + unregister_chrdev_region(devID, WMT_DEV_NUM); + gWmtMajor = -1; + } + + WMT_ERR_FUNC("fail \n"); + + return -1; +} + +static void WMT_exit (void) +{ + dev_t dev = MKDEV(gWmtMajor, 0); + +#if defined(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OPEN) + wmt_tm_deinit_rt(); + wmt_tm_deinit(); +#endif + + wmt_lib_deinit(); + +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif + cdev_del(&gWmtCdev); + unregister_chrdev_region(dev, WMT_DEV_NUM); + gWmtMajor = -1; +#ifdef MTK_WMT_WAKELOCK_SUPPORT + WMT_WARN_FUNC("destroy func_on_off_wake_lock\n"); + wake_lock_destroy(&func_on_off_wake_lock); +#endif + + stp_drv_exit(); + + WMT_INFO_FUNC("done\n"); +} + +module_init(WMT_init); +module_exit(WMT_exit); +//MODULE_LICENSE("Proprietary"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek Inc WCN"); +MODULE_DESCRIPTION("MTK WCN combo driver for WMT function"); + +module_param(gWmtMajor, uint, 0); + + diff --git a/drivers/mtk_wcn_combo/common/linux/wmt_tm.c b/drivers/mtk_wcn_combo/common/linux/wmt_tm.c new file mode 100755 index 000000000000..5a6b71d4c3cd --- /dev/null +++ b/drivers/mtk_wcn_combo/common/linux/wmt_tm.c @@ -0,0 +1,1402 @@ +#if WMT_PLAT_ALPS + +#include +#include +#include +#include +#include "wmt_tm.h" +#include + +#include +#include +/* For using net dev + */ +#include +/* For using net dev - */ + +#if defined(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OPEN) + +static int wmt_tm_debug_log = 0; +#define wmt_tm_dprintk(fmt, args...) \ +do { \ + if (wmt_tm_debug_log) { \ + xlog_printk(ANDROID_LOG_DEBUG, "Power/WMT_Thermal", fmt, ##args); \ + } \ +} while(0) + +#define wmt_tm_printk(fmt, args...) \ +do { \ + xlog_printk(ANDROID_LOG_DEBUG, "Power/WMT_Thermal", fmt, ##args); \ +} while(0) + +#define wmt_tm_info(fmt, args...) \ +do { \ + xlog_printk(ANDROID_LOG_INFO, "Power/WMT_Thermal", fmt, ##args); \ +} while(0) + +struct linux_thermal_ctrl_if { + int kernel_mode; + int interval; + struct thermal_zone_device *thz_dev; + struct thermal_cooling_device *cl_dev; + struct thermal_cooling_device *cl_pa1_dev; + struct thermal_cooling_device *cl_pa2_dev; + struct thermal_cooling_device *cl_pa3_dev; +}; + +struct wmt_thermal_ctrl_if { + struct wmt_thermal_ctrl_ops ops; +}; + +typedef struct wmt_tm { + struct linux_thermal_ctrl_if linux_if; + struct wmt_thermal_ctrl_if wmt_if; +}wmt_tm_t; + +struct wmt_stats { + unsigned long pre_time; + unsigned long pre_tx_bytes; +}; + +static struct timer_list wmt_stats_timer; +static struct wmt_stats wmt_stats_info; +static unsigned long pre_time; +static unsigned long tx_throughput; + +/*New Wifi throttling Algo+*/ +//over_up_time * polling interval > up_duration --> throttling +static unsigned int over_up_time = 0; //polling time +static unsigned int up_duration = 30; //sec +static unsigned int up_denominator = 2; +static unsigned int up_numerator = 1; + +//below_low_time * polling interval > low_duration --> throttling +static unsigned int below_low_time = 0; //polling time +static unsigned int low_duration = 10; //sec +static unsigned int low_denominator = 2; +static unsigned int low_numerator = 3; + +static unsigned int low_rst_time = 0; +static unsigned int low_rst_max = 3; +/*New Wifi throttling Algo-*/ + +#define MAX_LEN 256 +#define COOLER_THRO_NUM 3 +#define COOLER_NUM 10 +#define ONE_MBITS_PER_SEC 1000 + +static unsigned int tm_pid = 0; +static unsigned int tm_input_pid = 0; +static unsigned int tm_wfd_stat = 0; +static struct task_struct g_task; +static struct task_struct *pg_task = &g_task; + +/* +Cooler info+ */ +static int g_num_trip = COOLER_THRO_NUM + 1; +static char g_bind0[20]="mtktswmt-pa1"; +static char g_bind1[20]="mtktswmt-pa2"; +static char g_bind2[20]="mtktswmt-pa3"; +static char g_bind3[20]="mtktswmt-sysrst"; +static char g_bind4[20]={0}; +static char g_bind5[20]={0}; +static char g_bind6[20]={0}; +static char g_bind7[20]={0}; +static char g_bind8[20]={0}; +static char g_bind9[20]={0}; + + +static unsigned int cl_dev_state =0; +static unsigned int cl_pa1_dev_state =0; +static unsigned int cl_pa2_dev_state =0; +/*static unsigned int cl_pa3_dev_state =0;*/ +static unsigned int g_trip_temp[COOLER_NUM] = {85000,85000,85000,85000,0,0,0,0,0,0}; +/*static int g_thro[COOLER_THRO_NUM] = {10 * ONE_MBITS_PER_SEC, 5 * ONE_MBITS_PER_SEC, 1 * ONE_MBITS_PER_SEC};*/ +static int g_thermal_trip[COOLER_NUM] = {0,0,0,0,0,0,0,0,0,0}; +/* -Cooler info- */ + +wmt_tm_t g_wmt_tm; +wmt_tm_t *pg_wmt_tm = &g_wmt_tm; + +static int wmt_thz_bind(struct thermal_zone_device *, + struct thermal_cooling_device *); +static int wmt_thz_unbind(struct thermal_zone_device *, + struct thermal_cooling_device *); +static int wmt_thz_get_temp(struct thermal_zone_device *, + unsigned long *); +static int wmt_thz_get_mode(struct thermal_zone_device *, + enum thermal_device_mode *); +static int wmt_thz_set_mode(struct thermal_zone_device *, + enum thermal_device_mode); +static int wmt_thz_get_trip_type(struct thermal_zone_device *, int, + enum thermal_trip_type *); +static int wmt_thz_get_trip_temp(struct thermal_zone_device *, int, + unsigned long *); +static int wmt_thz_get_crit_temp(struct thermal_zone_device *, + unsigned long *); +static int wmt_cl_get_max_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_get_cur_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_set_cur_state(struct thermal_cooling_device *, + unsigned long); + +static int wmt_cl_pa1_get_max_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa1_get_cur_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa1_set_cur_state(struct thermal_cooling_device *, + unsigned long); + +static int wmt_cl_pa2_get_max_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa2_get_cur_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa2_set_cur_state(struct thermal_cooling_device *, + unsigned long); + +#ifdef NEVER +static int wmt_cl_pa3_get_max_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa3_get_cur_state(struct thermal_cooling_device *, + unsigned long *); +static int wmt_cl_pa3_set_cur_state(struct thermal_cooling_device *, + unsigned long); +#endif /* NEVER */ + +static struct thermal_zone_device_ops wmt_thz_dev_ops = { + .bind = wmt_thz_bind, + .unbind = wmt_thz_unbind, + .get_temp = wmt_thz_get_temp, + .get_mode = wmt_thz_get_mode, + .set_mode = wmt_thz_set_mode, + .get_trip_type = wmt_thz_get_trip_type, + .get_trip_temp = wmt_thz_get_trip_temp, + .get_crit_temp = wmt_thz_get_crit_temp, +}; + +static struct thermal_cooling_device_ops mtktspa_cooling_sysrst_ops = { + .get_max_state = wmt_cl_get_max_state, + .get_cur_state = wmt_cl_get_cur_state, + .set_cur_state = wmt_cl_set_cur_state, +}; + +static struct thermal_cooling_device_ops mtktspa_cooling_pa1_ops = { + .get_max_state = wmt_cl_pa1_get_max_state, + .get_cur_state = wmt_cl_pa1_get_cur_state, + .set_cur_state = wmt_cl_pa1_set_cur_state, +}; + +static struct thermal_cooling_device_ops mtktspa_cooling_pa2_ops = { + .get_max_state = wmt_cl_pa2_get_max_state, + .get_cur_state = wmt_cl_pa2_get_cur_state, + .set_cur_state = wmt_cl_pa2_set_cur_state, +}; + +#ifdef NEVER +static struct thermal_cooling_device_ops mtktspa_cooling_pa3_ops = { + .get_max_state = wmt_cl_pa3_get_max_state, + .get_cur_state = wmt_cl_pa3_get_cur_state, + .set_cur_state = wmt_cl_pa3_set_cur_state, +}; +#endif /* NEVER */ + +static unsigned long get_tx_bytes(void) +{ + struct net_device *dev; + struct net *net; + unsigned long tx_bytes = 0; + + read_lock(&dev_base_lock); + for_each_net(net) { + for_each_netdev(net, dev) { + if(!strncmp(dev->name, "wlan", 4) || !strncmp(dev->name, "ap", 2) || !strncmp(dev->name, "p2p", 3)) { + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); + tx_bytes = tx_bytes + stats->tx_bytes; + } + } + } + read_unlock(&dev_base_lock); + return tx_bytes; +} + +static int wmt_cal_stats(unsigned long data) +{ + struct wmt_stats *stats_info = (struct wmt_stats*) data; + struct timeval cur_time; + + wmt_tm_dprintk("[%s] pre_time=%lu, pre_data=%lu\n", __func__, pre_time, stats_info->pre_tx_bytes); + + do_gettimeofday(&cur_time); + + if (pre_time != 0 && cur_time.tv_sec > pre_time) { + unsigned long tx_bytes = get_tx_bytes(); + if (tx_bytes > stats_info->pre_tx_bytes) { + + tx_throughput = ((tx_bytes - stats_info->pre_tx_bytes) / (cur_time.tv_sec - pre_time)) >> 7; + + wmt_tm_dprintk("[%s] cur_time=%lu, cur_data=%lu, tx_throughput=%luKb/s\n", __func__, cur_time.tv_sec, tx_bytes, tx_throughput ); + + stats_info->pre_tx_bytes = tx_bytes; + } else if (tx_bytes < stats_info->pre_tx_bytes) { + /* Overflow */ + tx_throughput = ((0xffffffff - stats_info->pre_tx_bytes + tx_bytes) / (cur_time.tv_sec - pre_time)) >> 7;; + stats_info->pre_tx_bytes = tx_bytes; + wmt_tm_dprintk("[%s] cur_tx(%lu) < pre_tx\n", __func__, tx_bytes); + } else { + /* No traffic */ + tx_throughput = 0; + wmt_tm_dprintk("[%s] cur_tx(%lu) = pre_tx\n", __func__, tx_bytes); + } + } else { + /* Overflow possible ??*/ + tx_throughput = 0; + wmt_tm_printk("[%s] cur_time(%lu) < pre_time\n", __func__, cur_time.tv_sec); + } + + pre_time = cur_time.tv_sec; + wmt_tm_dprintk("[%s] pre_time=%lu, tv_sec=%lu\n",__func__, pre_time, cur_time.tv_sec); + + wmt_stats_timer.expires = jiffies + 1 * HZ; + add_timer(&wmt_stats_timer); + return 0; +} + +static int wmt_thz_bind(struct thermal_zone_device *thz_dev, + struct thermal_cooling_device *cool_dev) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + int table_val = 0; + + wmt_tm_dprintk("[%s]\n", __func__); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + return -EINVAL; + } + #ifdef NEVER + /* cooling devices */ + if (cool_dev != p_linux_if->cl_dev) + { + return 0; + } + #endif + + if(!strcmp(cool_dev->type, g_bind0)) { + table_val = 0; + wmt_tm_printk("[%s] %s\n", __func__, cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind1)) { + table_val = 1; + wmt_tm_printk("[%s] %s\n", __func__, cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind2)) { + table_val = 2; + wmt_tm_printk("[%s]] %s\n", __func__, cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind3)) { + table_val = 3; + wmt_tm_printk("[%s]] %s\n", __func__, cool_dev->type); + } else + return 0; + + if (mtk_thermal_zone_bind_cooling_device(thz_dev, table_val, cool_dev)) { + wmt_tm_info("[%s] binding fail\n", __func__); + return -EINVAL; + } else { + wmt_tm_printk("[%s]] binding OK\n", __func__); + } + + return 0; + +} +static int wmt_thz_unbind(struct thermal_zone_device *thz_dev, + struct thermal_cooling_device *cool_dev) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + int table_val = 0; + + wmt_tm_dprintk("[wmt_thz_unbind] \n"); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + return -EINVAL; + } +#if 0 + /* cooling devices */ + if (cool_dev == p_linux_if->cl_dev) + { + table_val= 0; + } + else + { + wmt_tm_dprintk("[wmt_thz_unbind] unbind device fail..!\n"); + return -EINVAL; + } +#endif + + if(!strcmp(cool_dev->type, g_bind0)) { + table_val = 0; + wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind1)) { + table_val = 1; + wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind2)) { + table_val = 2; + wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type); + } else if(!strcmp(cool_dev->type, g_bind3)) { + table_val = 3; + wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type); + } else + return 0; + + if (thermal_zone_unbind_cooling_device(thz_dev, table_val, cool_dev)) { + wmt_tm_info("[wmt_thz_unbind] error unbinding cooling dev\n"); + return -EINVAL; + } else { + wmt_tm_printk("[wmt_thz_unbind] unbinding OK\n"); + } + + return 0; +} + +static int wmt_thz_get_temp(struct thermal_zone_device *thz_dev, + unsigned long *pv) +{ + struct wmt_thermal_ctrl_ops *p_des; + int temp = 0; + + *pv = 0; + if(pg_wmt_tm) { + p_des = &pg_wmt_tm->wmt_if.ops; + temp = p_des->query_temp(); + + //temp = ((temp & 0x80) == 0x0)?temp:(-1)*temp ; + temp = ((temp & 0x80) == 0x0)?temp:(-1)*(temp & 0x7f); + *pv = temp*1000; + + wmt_tm_dprintk("[wmt_thz_get_temp] temp = %d\n", temp); + + if(temp > 100 || temp < 5) + wmt_tm_info("[wmt_thz_get_temp] temp = %d\n", temp); + } + + return 0; +} + +static int wmt_thz_get_mode(struct thermal_zone_device *thz_dev, + enum thermal_device_mode *mode) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; +// int kernel_mode = 0; + + wmt_tm_dprintk("[%s]\n", __func__); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + wmt_tm_dprintk("[%s] fail! \n", __func__); + return -EINVAL; + } + + wmt_tm_dprintk("[%s] %d\n", __func__, p_linux_if->kernel_mode); + + *mode = (p_linux_if->kernel_mode) ? THERMAL_DEVICE_ENABLED + : THERMAL_DEVICE_DISABLED; + + return 0; +} + +static int wmt_thz_set_mode(struct thermal_zone_device *thz_dev, + enum thermal_device_mode mode) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + + wmt_tm_dprintk("[%s]\n", __func__); + + + if(pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + wmt_tm_dprintk("[%s] fail! \n", __func__); + return -EINVAL; + } + + wmt_tm_dprintk("[%s] %d\n", __func__, mode); + + p_linux_if->kernel_mode = mode; + + return 0; + +} + +static int wmt_thz_get_trip_type(struct thermal_zone_device *thz_dev, int trip, + enum thermal_trip_type *type) +{ + wmt_tm_dprintk("[mtktspa_get_trip_type] %d\n", trip); + *type = g_thermal_trip[trip]; + return 0; +} + +static int wmt_thz_get_trip_temp(struct thermal_zone_device *thz_dev, int trip, + unsigned long *pv) +{ + wmt_tm_dprintk("[mtktspa_get_trip_temp] %d\n", trip); + *pv = g_trip_temp[trip]; + return 0; +} + +static int wmt_thz_get_crit_temp(struct thermal_zone_device *thz_dev, + unsigned long *pv) +{ + wmt_tm_dprintk("[%s]\n", __func__); +#define WMT_TM_TEMP_CRIT 85000 /* 85.000 degree Celsius */ + *pv = WMT_TM_TEMP_CRIT; + + return 0; +} + +/* +mtktspa_cooling_sysrst_ops+ */ +static int wmt_cl_get_max_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = 1; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_get_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = cl_dev_state; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_set_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long v) +{ + wmt_tm_dprintk("[%s] %d\n", __func__, v); + cl_dev_state = v; + + if (cl_dev_state == 1) { + //the temperature is over than the critical, system reboot. + BUG(); + } + + return 0; +} +/* -mtktspa_cooling_sysrst_ops- */ + +static int wmt_send_signal(int level) +{ + int ret = 0; + int thro = level; + + if (tm_input_pid == 0) { + wmt_tm_dprintk("[%s] pid is empty\n", __func__); + ret = -1; + } + + wmt_tm_printk("[%s] pid is %d, %d, %d\n", __func__, tm_pid, tm_input_pid, thro); + + if (ret == 0 && tm_input_pid != tm_pid) { + tm_pid = tm_input_pid; + pg_task = get_pid_task(find_vpid(tm_pid), PIDTYPE_PID); + } + + if (ret == 0 && pg_task) { + siginfo_t info; + info.si_signo = SIGIO; + info.si_errno = 0; + info.si_code = thro; + info.si_addr = NULL; + ret = send_sig_info(SIGIO, &info, pg_task); + } + + if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret); + + return ret; +} + +#define UNK_STAT -1 +#define LOW_STAT 0 +#define MID_STAT 1 +#define HIGH_STAT 2 +#define WFD_STAT 3 + +static inline unsigned long thro(unsigned long a, unsigned int b, unsigned int c) { + + unsigned long tmp; + + tmp = (a << 10) * b / c; + + return tmp >> 10; +} + +static int wmt_judge_throttling(int index, int is_on, int interval) +{ + /* + * throttling_stat + * 2 ( pa1=1,pa2=1 ) + * UPPER ---- + * 1 ( pa1=1,pa2=0 ) + * LOWER ---- + * 0 ( pa1=0,pa2=0 ) + */ + static unsigned int throttling_pre_stat = 0; + static int mail_box[2] = {-1,-1}; + + static bool is_reset = false; + + unsigned long cur_thro = tx_throughput; + static unsigned long thro_constraint = 99 * 1000; + + int cur_wifi_stat = 0; + + wmt_tm_dprintk("[%s]+ [0]=%d, [1]=%d || [%d] is %s\n", __func__, mail_box[0], mail_box[1], + index, (is_on==1?"ON":"OFF")); + mail_box[index] = is_on; + + if (mail_box[0] >= 0 && mail_box[1] >= 0) { + cur_wifi_stat = mail_box[0] + mail_box[1]; + + /* + * If Wifi-display is on, go to WFD_STAT state, and reset the throttling. + */ + if (tm_wfd_stat == 2) + cur_wifi_stat = WFD_STAT; + + switch(cur_wifi_stat) { + case WFD_STAT: + if (throttling_pre_stat != WFD_STAT) { + /* + * Enter Wifi-Display status, reset all throttling. Dont affect the performance of Wifi-Display. + */ + wmt_send_signal(-1); + below_low_time = 0; + over_up_time = 0; + throttling_pre_stat = WFD_STAT; + wmt_tm_printk("WFD is on, reset everything!"); + } + break; + + case HIGH_STAT: + if (throttling_pre_stat < HIGH_STAT || throttling_pre_stat == WFD_STAT) { + if (cur_thro > 0) /*Wifi is working!!*/ + thro_constraint = thro(cur_thro, up_numerator, up_denominator); + else /*At this moment, current throughput is none. Use the previous constraint.*/ + thro_constraint = thro(thro_constraint, up_numerator, up_denominator); + + wmt_tm_printk("LOW/MID-->HIGH:%lu <- (%d / %d) %lu", thro_constraint, up_numerator, up_denominator, cur_thro); + + wmt_send_signal( thro_constraint/1000 ); + throttling_pre_stat = HIGH_STAT; + over_up_time = 0; + } else if (throttling_pre_stat == HIGH_STAT) { + over_up_time++; + if ( (over_up_time * interval) >= up_duration) { + if (cur_thro < thro_constraint) /*real throughput may have huge variant*/ + thro_constraint = thro(cur_thro, up_numerator, up_denominator); + else /* current throughput is large than constraint. WHAT!!!*/ + thro_constraint = thro(thro_constraint, up_numerator, up_denominator); + + wmt_tm_printk("HIGH-->HIGH:%lu <- (%d / %d) %lu", thro_constraint, up_numerator, up_denominator, cur_thro); + + wmt_send_signal( thro_constraint/1000 ); + over_up_time = 0; + } + } else { + wmt_tm_info("[%s] Error state1!!\n", __func__, throttling_pre_stat); + } + wmt_tm_printk("case2 time=%d\n", over_up_time); + break; + + case MID_STAT: + if (throttling_pre_stat == LOW_STAT) { + below_low_time = 0; + throttling_pre_stat = MID_STAT; + wmt_tm_printk("[%s] Go up!!\n", __func__); + } else if (throttling_pre_stat == HIGH_STAT) { + over_up_time = 0; + throttling_pre_stat = MID_STAT; + wmt_tm_printk("[%s] Go down!!\n", __func__); + } else { + throttling_pre_stat = MID_STAT; + wmt_tm_dprintk("[%s] pre_stat=%d!!\n", __func__, throttling_pre_stat); + } + break; + + case LOW_STAT: + if (throttling_pre_stat == WFD_STAT) { + throttling_pre_stat = LOW_STAT; + wmt_tm_dprintk("[%s] pre_stat=%d!!\n", __func__, throttling_pre_stat); + } else if (throttling_pre_stat > LOW_STAT) { + if (cur_thro < 5000 && cur_thro > 0) { + thro_constraint = cur_thro * 3; + } else if (cur_thro >= 5000) { + thro_constraint = thro(cur_thro, low_numerator, low_denominator); + } else { + thro_constraint = thro(thro_constraint, low_numerator, low_denominator); + } + + wmt_tm_printk("MID/HIGH-->LOW:%lu <- (%d / %d) %lu", thro_constraint, low_numerator, low_denominator, cur_thro); + wmt_send_signal( thro_constraint/1000 ); + throttling_pre_stat = LOW_STAT; + below_low_time = 0; + low_rst_time = 0; + is_reset = false; + } else if (throttling_pre_stat == LOW_STAT) { + below_low_time++; + if ( (below_low_time*interval) >= low_duration) { + if (low_rst_time >= low_rst_max && !is_reset) { + wmt_tm_printk("over rst time=%d", low_rst_time); + + wmt_send_signal(-1); //reset + low_rst_time = low_rst_max; + is_reset = true; + } else if(!is_reset) { + if (cur_thro < 5000 && cur_thro > 0) { + thro_constraint = cur_thro * 3; + } else if (cur_thro >= 5000) { + thro_constraint = thro(cur_thro, low_numerator, low_denominator); + low_rst_time++; + } else { + thro_constraint = thro(thro_constraint, low_numerator, low_denominator); + low_rst_time++; + } + + wmt_tm_printk("LOW-->LOW:%lu <-(%d / %d) %lu", thro_constraint, low_numerator, low_denominator, cur_thro); + + wmt_send_signal( thro_constraint/1000 ); + below_low_time = 0; + } else { + wmt_tm_dprintk("Have reset, no control!!"); + } + } + } else { + wmt_tm_info("[%s] Error state3 %d!!\n", __func__, throttling_pre_stat); + } + wmt_tm_dprintk("case0 time=%d, rst=%d %d\n", below_low_time, low_rst_time, is_reset); + break; + + default: + wmt_tm_info("[%s] Error cur_wifi_stat=%d!!\n", __func__, cur_wifi_stat); + break; + } + + mail_box[0] = UNK_STAT; + mail_box[1] = UNK_STAT; + } else { + wmt_tm_dprintk("[%s] dont get all info!!\n", __func__); + } + return 0; +} + +/* +mtktspa_cooling_pa1_ops+ */ +static int wmt_cl_pa1_get_max_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = 1; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa1_get_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = cl_pa1_dev_state; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa1_set_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long v) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + int ret = 0; + + wmt_tm_dprintk("[%s] %d\n", __func__, v); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + ret = -1; + } + + cl_pa1_dev_state = (unsigned int)v; + + if (cl_pa1_dev_state == 1) { + ret = wmt_judge_throttling(0, 1, p_linux_if->interval/1000); + } else { + ret = wmt_judge_throttling(0, 0, p_linux_if->interval/1000); + } + if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret); + return ret; +} +/* -mtktspa_cooling_pa1_ops- */ + +/* +mtktspa_cooling_pa2_ops+ */ +static int wmt_cl_pa2_get_max_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = 1; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa2_get_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = cl_pa2_dev_state; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa2_set_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long v) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + int ret = 0; + + wmt_tm_dprintk("[%s] %d\n", __func__, v); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + ret = -1; + } + + cl_pa2_dev_state = (unsigned int)v; + + if (cl_pa2_dev_state == 1) { + ret = wmt_judge_throttling(1, 1, p_linux_if->interval/1000); + } else { + ret = wmt_judge_throttling(1, 0, p_linux_if->interval/1000); + } + if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret); + return ret; +} +/* -mtktspa_cooling_pa2_ops- */ + +#ifdef NEVER +/* +mtktspa_cooling_pa3_ops+ */ +static int wmt_cl_pa3_get_max_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = 1; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa3_get_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long *pv) +{ + *pv = cl_pa3_dev_state; + wmt_tm_dprintk("[%s] %d\n", __func__, *pv); + return 0; +} + +static int wmt_cl_pa3_set_cur_state(struct thermal_cooling_device *cool_dev, + unsigned long v) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + int ret = 0; + + wmt_tm_dprintk("[%s] %d\n", __func__, v); + + if (pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + ret = -1; + } + + cl_pa3_dev_state = (unsigned int)v; + + if (cl_pa3_dev_state == 1) { + //ret = wmt_arbitrate_thro(2,3); + } else { + //ret = wmt_arbitrate_thro(2,0); + } + if (ret != 0) wmt_tm_printk("[%s] ret=%d\n", __func__, ret); + return ret; +} +/* -mtktspa_cooling_pa3_ops- */ +#endif /* NEVER */ + +int wmt_wifi_tx_thro_read( char *buf, char **start, off_t offset, int count, int *eof, void *data ) +{ + count = sprintf(buf, "%lu\n", tx_throughput); + + wmt_tm_dprintk("[%s] tx=%lu\n", __func__, tx_throughput); + + return count; +} + +/*New Wifi throttling Algo+*/ +ssize_t wmt_wifi_algo_write( struct file *filp, const char __user *buf, unsigned long len, void *data ) +{ + char desc[MAX_LEN] = {0}; + + unsigned int tmp_up_dur = 30; + unsigned int tmp_up_den = 2; + unsigned int tmp_up_num = 1; + + unsigned int tmp_low_dur = 3; + unsigned int tmp_low_den = 2; + unsigned int tmp_low_num = 3; + + unsigned int tmp_low_rst_max = 3; + + unsigned int tmp_log = 0; + + len = (len < (sizeof(desc) - 1)) ? len : (sizeof(desc) - 1); + + /* write data to the buffer */ + if (copy_from_user(desc, buf, len)) { + return -EFAULT; + } + + if (sscanf(desc, "%d %d/%d, %d %d/%d, %d", &tmp_up_dur, &tmp_up_num, &tmp_up_den, &tmp_low_dur, \ + &tmp_low_num, &tmp_low_den, &tmp_low_rst_max) == 7) { + + up_duration = tmp_up_dur; + up_denominator = tmp_up_den; + up_numerator = tmp_up_num; + + low_duration = tmp_low_dur; + low_denominator = tmp_low_den; + low_numerator = tmp_low_num; + + low_rst_max = tmp_low_rst_max; + + over_up_time = 0; + below_low_time = 0; + low_rst_time = 0; + + wmt_tm_printk("[%s] %s [up]%d %d/%d, [low]%d %d/%d, rst=%d\n", __func__, desc, up_duration, \ + up_numerator, up_denominator, low_duration, low_numerator, low_denominator, low_rst_max); + + return len; + } else if (sscanf(desc, "log=%d", &tmp_log) == 1) { + if (tmp_log == 1) + wmt_tm_debug_log = 1; + else + wmt_tm_debug_log = 0; + + return len; + } else { + wmt_tm_printk("[%s] bad argument = %s\n", __func__, desc); + } + return -EINVAL; +} + +int wmt_wifi_algo_read( char *buf, char **start, off_t offset, int count, int *eof, void *data ) +{ + int ret; + char tmp[MAX_LEN] = {0}; + + sprintf(tmp, "[up]\t%3d(sec)\t%2d/%2d\n[low]\t%3d(sec)\t%2d/%2d\nrst=%2d\n", up_duration, up_numerator, up_denominator, \ + low_duration, low_numerator, low_denominator, low_rst_max); + ret = strlen(tmp); + + memcpy(buf, tmp, ret*sizeof(char)); + + wmt_tm_printk("[%s] [up]%d %d/%d, [low]%d %d/%d, rst=%d\n", __func__, up_duration, \ + up_numerator, up_denominator, low_duration, low_numerator, low_denominator, low_rst_max); + + return ret; +} +/*New Wifi throttling Algo-*/ + +ssize_t wmt_tm_wfd_write( struct file *filp, const char __user *buf, unsigned long len, void *data ) +{ + int ret = 0; + char tmp[MAX_LEN] = {0}; + + /* write data to the buffer */ + if (copy_from_user(tmp, buf, len)) { + return -EFAULT; + } + + ret = sscanf(tmp, "%d", &tm_wfd_stat); + + wmt_tm_printk("[%s] %s = %d, len=%d, ret=%d\n", __func__, tmp, tm_wfd_stat, len, ret); + + return len; +} + +int wmt_tm_wfd_read( char *buf, char **start, off_t offset , int count, int *eof, void *data ) +{ + int len; + int ret = 0; + char tmp[MAX_LEN] = {0}; + + ret = sprintf(tmp, "%d", tm_wfd_stat); + len = strlen(tmp); + + memcpy(buf, tmp, ret*sizeof(char)); + + wmt_tm_printk("[%s] %s = %d, len=%d, ret=%d\n", __func__, tmp, tm_wfd_stat, len, ret); + + return ret; +} + +ssize_t wmt_tm_pid_write( struct file *filp, const char __user *buf, unsigned long len, void *data ) +{ + int ret = 0; + char tmp[MAX_LEN] = {0}; + + /* write data to the buffer */ + if ( copy_from_user(tmp, buf, len) ) { + return -EFAULT; + } + + ret = kstrtouint(tmp, 10, &tm_input_pid); + if (ret) + WARN_ON(1); + + wmt_tm_printk("[%s] %s = %d\n", __func__, tmp, tm_input_pid); + + return len; +} + +int wmt_tm_pid_read( char *buf, char **start, off_t offset , int count, int *eof, void *data ) +{ + int ret; + char tmp[MAX_LEN] = {0}; + + sprintf(tmp, "%d", tm_input_pid); + ret = strlen(tmp); + + memcpy(buf, tmp, ret*sizeof(char)); + + wmt_tm_printk("[%s] %s = %d\n", __func__, buf, tm_input_pid); + + return ret; +} + +#define check_str(x) (x[0]=='\0'?"none\t":x) + +static int wmt_tm_read(char *buf, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + char *p = buf; + struct linux_thermal_ctrl_if *p_linux_if = 0; + + wmt_tm_printk("[%s]\n", __func__); + + //sanity + if(pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + wmt_tm_info("[wmt_tm_read] fail! \n"); + return -EINVAL; + } + + p += sprintf(p, "[wmt_tm_read]"\ + "\n \tcooler\t\ttrip_temp\ttrip_type" \ + "\n [0] %s\t%d\t\t%d" \ + "\n [1] %s\t%d\t\t%d" \ + "\n [2] %s\t%d\t\t%d" \ + "\n [3] %s\t%d\t\t%d" \ + "\n [4] %s\t%d\t\t%d" \ + "\n [5] %s\t%d\t\t%d" \ + "\n [6] %s\t%d\t\t%d" \ + "\n [7] %s\t%d\t\t%d" \ + "\n [8] %s\t%d\t\t%d" \ + "\n [9] %s\t%d\t\t%d" \ + "\ntime_ms=%d\n", \ + check_str(g_bind0),g_trip_temp[0],g_thermal_trip[0], check_str(g_bind1),g_trip_temp[1],g_thermal_trip[1],\ + check_str(g_bind2),g_trip_temp[2],g_thermal_trip[2], check_str(g_bind3),g_trip_temp[3],g_thermal_trip[3],\ + check_str(g_bind4),g_trip_temp[4],g_thermal_trip[4], check_str(g_bind5),g_trip_temp[5],g_thermal_trip[5],\ + check_str(g_bind6),g_trip_temp[6],g_thermal_trip[6], check_str(g_bind7),g_trip_temp[7],g_thermal_trip[7],\ + check_str(g_bind8),g_trip_temp[8],g_thermal_trip[8], check_str(g_bind9),g_trip_temp[9],g_thermal_trip[9],\ + p_linux_if->interval); + + *start = buf + off; + + len = p - buf; + if (len > off) + len -= off; + else + len = 0; + + return len < count ? len : count; +} + +static ssize_t wmt_tm_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + int i = 0; + int len=0,time_msec=0; + int trip_temp[COOLER_NUM] = {0}; + int thermal_trip[COOLER_NUM] = {0}; + + char desc[512]; + char bind0[20],bind1[20],bind2[20],bind3[20],bind4[20]; + char bind5[20],bind6[20],bind7[20],bind8[20],bind9[20]; + + struct linux_thermal_ctrl_if *p_linux_if = 0; + + wmt_tm_printk("[%s]\n", __func__); + + //sanity + if(pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + wmt_tm_info("[wmt_thz_write] fail! \n"); + return -EINVAL; + } + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + + if (copy_from_user(desc, buffer, len)) { + return 0; + } + + desc[len] = '\0'; + + if (sscanf(desc, "%d %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d", + &g_num_trip, &trip_temp[0], &thermal_trip[0], bind0, + &trip_temp[1], &thermal_trip[1], bind1, + &trip_temp[2], &thermal_trip[2], bind2, + &trip_temp[3], &thermal_trip[3], bind3, + &trip_temp[4], &thermal_trip[4], bind4, + &trip_temp[5], &thermal_trip[5], bind5, + &trip_temp[6], &thermal_trip[6], bind6, + &trip_temp[7], &thermal_trip[7], bind7, + &trip_temp[8], &thermal_trip[8], bind8, + &trip_temp[9], &thermal_trip[9], bind9, + &time_msec) == 32) + { + // unregister + if (p_linux_if->thz_dev) { + mtk_thermal_zone_device_unregister(p_linux_if->thz_dev); + p_linux_if->thz_dev = NULL; + } + + for ( i = 0; i < g_num_trip; i++) { + g_thermal_trip[i] = thermal_trip[i]; + } + + g_bind0[0]=g_bind1[0]=g_bind2[0]=g_bind3[0]=g_bind4[0]='\0'; + g_bind5[0]=g_bind6[0]=g_bind7[0]=g_bind8[0]=g_bind9[0]='\0'; + + for ( i = 0; i < 20; i++ ) { + g_bind0[i]=bind0[i]; + g_bind1[i]=bind1[i]; + g_bind2[i]=bind2[i]; + g_bind3[i]=bind3[i]; + g_bind4[i]=bind4[i]; + g_bind5[i]=bind5[i]; + g_bind6[i]=bind6[i]; + g_bind7[i]=bind7[i]; + g_bind8[i]=bind8[i]; + g_bind9[i]=bind9[i]; + } + + for ( i = 0; i < g_num_trip; i++) { + g_trip_temp[i] = trip_temp[i]; + } + + p_linux_if->interval = time_msec; + + wmt_tm_printk("[wmt_tm_write] g_trip_temp [0]=%d, [1]=%d, [2]=%d, [3]=%d, [4]=%d\n", + g_thermal_trip[0], g_thermal_trip[1], g_thermal_trip[2], + g_thermal_trip[3], g_thermal_trip[4]); + + wmt_tm_printk("[wmt_tm_write] g_trip_temp [5]=%d, [6]=%d, [7]=%d, [8]=%d, [9]=%d\n", + g_thermal_trip[5], g_thermal_trip[6], g_thermal_trip[7], + g_thermal_trip[8], g_thermal_trip[9]); + + wmt_tm_printk("[wmt_tm_write] cooldev [0]=%s, [1]=%s, [2]=%s, [3]=%s, [4]=%s,\n", + g_bind0, g_bind1, g_bind2, g_bind3, g_bind4); + + wmt_tm_printk("[wmt_tm_write] cooldev [5]=%s, [6]=%s, [7]=%s, [8]=%s, [9]=%s,\n", + g_bind5, g_bind6, g_bind7, g_bind8, g_bind9); + + wmt_tm_printk("[wmt_tm_write] trip_temp [0]=%d, [1]=%d, [2]=%d, [3]=%d, [4]=%d\n", + trip_temp[0], trip_temp[1], trip_temp[2], trip_temp[3], trip_temp[4]); + + wmt_tm_printk("[wmt_tm_write] trip_temp [5]=%d, [6]=%d, [7]=%d, [8]=%d, [9]=%d\n", + trip_temp[5], trip_temp[6], trip_temp[7], trip_temp[8], trip_temp[9]); + + wmt_tm_printk("[wmt_tm_write] polling time=%d\n", p_linux_if->interval); + + //p_linux_if->thz_dev->polling_delay = p_linux_if->interval*1000; + + //thermal_zone_device_update(p_linux_if->thz_dev); + + // register + p_linux_if->thz_dev = mtk_thermal_zone_device_register("mtktswmt", g_num_trip, NULL, + &wmt_thz_dev_ops, 0, 0, 0, p_linux_if->interval); + + wmt_tm_printk("[wmt_tm_write] time_ms=%d\n", p_linux_if->interval); + + return count; + } else { + wmt_tm_info("[%s] bad argument = %s\n", __func__, desc); + } + + return -EINVAL; +} + +static int wmt_tm_proc_register(void) +{ + struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *wmt_tm_proc_dir = NULL; + + wmt_tm_printk("[%s]\n", __func__); + + wmt_tm_proc_dir = proc_mkdir("wmt_tm", NULL); + if (!wmt_tm_proc_dir) { + wmt_tm_printk("[wmt_tm_proc_register]: mkdir /proc/wmt_tm failed\n"); + } else { + entry = create_proc_entry("wmt_tm", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir); + if (entry) { + entry->read_proc = wmt_tm_read; + entry->write_proc = wmt_tm_write; + } + + entry = create_proc_entry("tm_pid", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir); + if (entry) { + entry->read_proc = wmt_tm_pid_read; + entry->write_proc = wmt_tm_pid_write; + } + + entry = create_proc_entry("wmt_val", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir); + if (entry) { + entry->read_proc = wmt_wifi_algo_read; + entry->write_proc = wmt_wifi_algo_write; + } + + entry = create_proc_entry("tx_thro", S_IRUGO | S_IWUSR, wmt_tm_proc_dir); + if (entry) { + entry->read_proc = wmt_wifi_tx_thro_read; + } + + entry = create_proc_entry("wfd_stat", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir); + if (entry) { + entry->read_proc = wmt_tm_wfd_read; + entry->write_proc = wmt_tm_wfd_write; + } + } + return 0; +} + +static int wmt_tm_proc_unregister(void) +{ + wmt_tm_printk("[%s]\n", __func__); + //remove_proc_entry("wmt_tm", proc_entry); + return 0; +} + +static int wmt_tm_thz_cl_register(void) +{ + #define DEFAULT_POLL_TIME 0 /*Default disable, turn on by thermal policy*/ + + struct linux_thermal_ctrl_if *p_linux_if = 0; + + wmt_tm_printk("[%s]\n", __func__); + + if(pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + return -1; + } + + /* cooling devices */ + p_linux_if->cl_dev = mtk_thermal_cooling_device_register("mtktswmt-sysrst", NULL, + &mtktspa_cooling_sysrst_ops); + + p_linux_if->cl_pa1_dev = mtk_thermal_cooling_device_register("mtktswmt-pa1", NULL, + &mtktspa_cooling_pa1_ops); + + p_linux_if->cl_pa2_dev = mtk_thermal_cooling_device_register("mtktswmt-pa2", NULL, + &mtktspa_cooling_pa2_ops); + +#ifdef NEVER + p_linux_if->cl_pa3_dev = mtk_thermal_cooling_device_register("mtktswmt-pa3", NULL, + &mtktspa_cooling_pa3_ops); +#endif /* NEVER */ + + p_linux_if->interval = DEFAULT_POLL_TIME; + + /* trips */ + p_linux_if->thz_dev = mtk_thermal_zone_device_register("mtktswmt", g_num_trip, NULL, + &wmt_thz_dev_ops, 0, 0, 0, p_linux_if->interval); + + return 0; +} + +static int wmt_tm_thz_cl_unregister(void) +{ + struct linux_thermal_ctrl_if *p_linux_if = 0; + + wmt_tm_printk("[%s]\n", __func__); + + if(pg_wmt_tm) { + p_linux_if = &pg_wmt_tm->linux_if; + } else { + return -1; + } + + if (p_linux_if->cl_dev) { + mtk_thermal_cooling_device_unregister(p_linux_if->cl_dev); + p_linux_if->cl_dev = NULL; + } + + if (p_linux_if->cl_pa1_dev) { + mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa1_dev); + p_linux_if->cl_pa1_dev = NULL; + } + + if (p_linux_if->cl_pa2_dev) { + mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa2_dev); + p_linux_if->cl_pa2_dev = NULL; + } + +#ifdef NEVER + if (p_linux_if->cl_pa3_dev) { + mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa3_dev); + p_linux_if->cl_pa3_dev = NULL; + } +#endif /* NEVER */ + + if (p_linux_if->thz_dev) { + mtk_thermal_zone_device_unregister(p_linux_if->thz_dev); + p_linux_if->thz_dev = NULL; + } + + return 0; +} + +static int wmt_tm_ops_register(struct wmt_thermal_ctrl_ops *ops) +{ + struct wmt_thermal_ctrl_ops *p_des; + + wmt_tm_printk("[%s]\n", __func__); + + if (pg_wmt_tm) { +#if 1 + p_des = &pg_wmt_tm->wmt_if.ops; + if (ops!=NULL) { + wmt_tm_printk("[wmt_tm_ops_register] reg start ...\n"); + p_des->query_temp = ops->query_temp; + p_des->set_temp = ops->set_temp; + wmt_tm_printk("[wmt_tm_ops_register] reg end ...\n"); + } else { + p_des->query_temp = 0; + p_des->set_temp = 0; + } +#endif + return 0; + } else { + return -1; + } +} + +static int wmt_tm_ops_unregister(void) +{ + struct wmt_thermal_ctrl_ops *p_des; + + wmt_tm_printk("[%s]\n", __func__); + + if (pg_wmt_tm) { + p_des = &pg_wmt_tm->wmt_if.ops; + p_des->query_temp = 0; + p_des->set_temp = 0; + + return 0; + } else { + return -1; + } +} + +int wmt_tm_init(struct wmt_thermal_ctrl_ops *ops) +{ + int err = 0; + + wmt_tm_printk("[wmt_tm_init] start -->\n"); + + err = wmt_tm_ops_register(ops); + if(err) + return err; + + err = wmt_tm_proc_register(); + if(err) + return err; + + /* init a timer for stats tx bytes */ + wmt_stats_info.pre_time = 0; + wmt_stats_info.pre_tx_bytes = 0; + + init_timer(&wmt_stats_timer); + wmt_stats_timer.function = (void *)&wmt_cal_stats; + wmt_stats_timer.data = (unsigned long) &wmt_stats_info; + wmt_stats_timer.expires = jiffies + 1 * HZ; + add_timer(&wmt_stats_timer); + +#if 0 + err = wmt_tm_thz_cl_register(); + if(err) + return err; +#endif + wmt_tm_printk("[wmt_tm_init] end <--\n"); + + return 0; +} + +int wmt_tm_init_rt() +{ + int err = 0; + + wmt_tm_printk("[wmt_tm_init_rt] start -->\n"); + + err = wmt_tm_thz_cl_register(); + if(err) + return err; + + wmt_tm_printk("[wmt_tm_init_rt] end <--\n"); + + return 0; +} + +int wmt_tm_deinit_rt() +{ + int err = 0; + + wmt_tm_printk("[wmt_tm_deinit_rt] start -->\n"); + + err = wmt_tm_thz_cl_unregister(); + if(err) + return err; + + wmt_tm_printk("[wmt_tm_deinit_rt] end <--\n"); + + return 0; +} + +int wmt_tm_deinit() +{ + int err = 0; + + wmt_tm_printk("[%s]\n", __func__); +#if 0 + err = wmt_tm_thz_cl_unregister(); + if(err) + return err; +#endif + err = wmt_tm_proc_unregister(); + if(err) + return err; + + err = wmt_tm_ops_unregister(); + if(err) + return err; + + del_timer(&wmt_stats_timer); + + return 0; +} +#endif +#endif + diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c new file mode 100755 index 000000000000..980ef5805881 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c @@ -0,0 +1,346 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CMB-HW]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal.h" +#include "mtk_wcn_cmb_hw.h" +#include "wmt_plat.h" +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define DFT_RTC_STABLE_TIME 100 +#define DFT_LDO_STABLE_TIME 100 +#define DFT_RST_STABLE_TIME 30 +#define DFT_OFF_STABLE_TIME 10 +#define DFT_ON_STABLE_TIME 30 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +PWR_SEQ_TIME gPwrSeqTime; + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 +mtk_wcn_cmb_hw_pwr_off (VOID) +{ + INT32 iRet = 0; + WMT_INFO_FUNC("CMB-HW, hw_pwr_off start\n"); + + /*1. disable irq --> should be done when do wmt-ic swDeinit period*/ + // TODO:[FixMe][GeorgeKuo] clarify this + + /*2. set bgf eint/all eint to deinit state, namely input low state*/ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ unregistered and set BGF_EINT GPIO to correct state!\n"); + /* 2.1 set ALL_EINT pin to correct state even it is not used currently */ + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, ALL_EINT IRQ unregistered and disabled\n"); + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_DEINIT); + /* 2.2 deinit gps sync */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT); + + /*3. set audio interface to CMB_STUB_AIF_0, BT PCM OFF, I2S OFF*/ + iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_0, CMB_STUB_AIF_CTRL_DIS); + + /*4. set control gpio into deinit state, namely input low state*/ + iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + + /*5. set uart tx/rx into deinit state, namely input low state*/ + iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_DEINIT); + + /* 6. Last, LDO output low */ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_L); + + /*7. deinit gps_lna*/ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT); + + WMT_INFO_FUNC("CMB-HW, hw_pwr_off finish\n"); + return iRet; +} + +INT32 +mtk_wcn_cmb_hw_pwr_on (VOID) +{ + static UINT32 _pwr_first_time = 1; + INT32 iRet = 0; + + WMT_INFO_FUNC("CMB-HW, hw_pwr_on start\n"); +#if 0 //IRQ should in inact state before power on, so this step is not needed + /* disable interrupt firstly */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); +#endif + /*set all control and eint gpio to init state, namely input low mode*/ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT); + // wmt_plat_gpio_ctrl(PIN_WIFI_EINT, PIN_STA_INIT); /* WIFI_EINT is controlled by SDIO host driver */ + // TODO: [FixMe][George]:WIFI_EINT is used in common SDIO + + /*1. pull high LDO to supply power to chip*/ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.ldoStableTime); + + /* 2. export RTC clock to chip*/ + if (_pwr_first_time) { + /* rtc clock should be output all the time, so no need to enable output again*/ + iRet += wmt_plat_gpio_ctrl(PIN_RTC, PIN_STA_INIT); + osal_msleep(gPwrSeqTime.rtcStableTime); + WMT_INFO_FUNC("CMB-HW, rtc clock exported\n"); + } + + /*3. set UART Tx/Rx to UART mode*/ + iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_INIT); + + /*4. PMU->output low, RST->output low, sleep off stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_msleep(gPwrSeqTime.offStableTime); + + /*5. PMU->output high, sleep rst stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.rstStableTime); + + /*6. RST->output high, sleep on stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.onStableTime); + + /*7. set audio interface to CMB_STUB_AIF_1, BT PCM ON, I2S OFF*/ + /* BT PCM bus default mode. Real control is done by audio */ + iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_1, CMB_STUB_AIF_CTRL_DIS); + + /*8. set EINT< -ommited-> move this to WMT-IC module, where common sdio interface will be identified and do proper operation*/ + // TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ registered and disabled \n"); + + /* 8.1 set ALL_EINT pin to correct state even it is not used currently */ + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_MUX); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, hw_pwr_on finish (%d)\n", iRet); + + _pwr_first_time = 0; + return iRet; + +} + +INT32 +mtk_wcn_cmb_hw_rst (VOID) +{ + INT32 iRet = 0; + WMT_INFO_FUNC("CMB-HW, hw_rst start, eirq should be disabled before this step\n"); + + /*1. PMU->output low, RST->output low, sleep off stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_msleep(gPwrSeqTime.offStableTime); + + /*2. PMU->output high, sleep rst stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.rstStableTime); + + /*3. RST->output high, sleep on stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.onStableTime); + WMT_INFO_FUNC("CMB-HW, hw_rst finish, eirq should be enabled after this step\n"); + return 0; +} + +static VOID +mtk_wcn_cmb_hw_dmp_seq (VOID) +{ + PUINT32 pTimeSlot = (PUINT32)&gPwrSeqTime; + WMT_INFO_FUNC("combo chip power on sequence time, RTC (%d), LDO (%d), RST(%d), OFF(%d), ON(%d)\n", + pTimeSlot[0], /**pTimeSlot++,*/ + pTimeSlot[1], + pTimeSlot[2], + pTimeSlot[3], + pTimeSlot[4] + ); + return; +} + +INT32 +mtk_wcn_cmb_hw_init ( + P_PWR_SEQ_TIME pPwrSeqTime + ) +{ + if (NULL != pPwrSeqTime && + pPwrSeqTime->ldoStableTime > 0 && + pPwrSeqTime->rtcStableTime > 0 && + pPwrSeqTime->offStableTime > DFT_OFF_STABLE_TIME && + pPwrSeqTime->onStableTime > DFT_ON_STABLE_TIME && + pPwrSeqTime->rstStableTime > DFT_RST_STABLE_TIME + ) { + /*memcpy may be more performance*/ + WMT_DBG_FUNC("setting hw init sequence parameters\n"); + osal_memcpy(&gPwrSeqTime, pPwrSeqTime, osal_sizeof(gPwrSeqTime)); + } + else { + WMT_WARN_FUNC("invalid pPwrSeqTime parameter, use default hw init sequence parameters\n"); + gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME; + gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME; + gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME; + gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME; + gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME; + } + mtk_wcn_cmb_hw_dmp_seq(); + return 0; +} + +INT32 +mtk_wcn_cmb_hw_deinit (VOID) +{ + + WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit start, set to default hw init sequence parameters\n"); + gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME; + gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME; + gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME; + gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME; + gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME; + WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit finish\n"); + return 0; +} + diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c new file mode 100755 index 000000000000..69546c061c29 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c @@ -0,0 +1,348 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CMB_STUB_LOG_INFO(fmt, arg...) printk(KERN_INFO fmt, ##arg) +#define CMB_STUB_LOG_WARN(fmt, arg...) printk(KERN_WARNING fmt, ##arg) +#define CMB_STUB_LOG_DBG(fmt, arg...) printk(KERN_DEBUG fmt, ##arg) + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +//#include +//#include /* clr_device_working_ability, MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE, MT65XX_PDN_PERI_MSDC2 */ +//#include +// TODO: [FixMe][GeorgeKuo] keep prototype unchanged temporarily. Replace it +// when integrate MT6628 & ALPS & other built-in modules, such as AUDIO. +//#include + +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb = NULL; +static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb = NULL; +static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0; + +/* A temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X. + * This is used for ALPS backward compatible ONLY!!! Remove this table, related + * functions, and type definition after modifying other kernel built-in modules, + * such as AUDIO. [FixMe][GeorgeKuo] + */ +static CMB_STUB_AIF_X audio2aif[] = { + [COMBO_AUDIO_STATE_0] = CMB_STUB_AIF_0, + [COMBO_AUDIO_STATE_1] = CMB_STUB_AIF_1, + [COMBO_AUDIO_STATE_2] = CMB_STUB_AIF_2, + [COMBO_AUDIO_STATE_3] = CMB_STUB_AIF_3, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief A registration function for WMT-PLAT to register itself to CMB-STUB. + * + * An MTK-WCN-CMB-STUB registration function provided to WMT-PLAT to register + * itself and related callback functions when driver being loaded into kernel. + * + * \param p_stub_cb a pointer carrying CMB_STUB_CB information + * + * \retval 0 operation success + * \retval -1 invalid parameters + */ +int +mtk_wcn_cmb_stub_reg (P_CMB_STUB_CB p_stub_cb) +{ + if ( (!p_stub_cb ) + || (p_stub_cb->size != sizeof(CMB_STUB_CB)) ) { + CMB_STUB_LOG_WARN( "[cmb_stub] invalid p_stub_cb:0x%p size(%d)\n", + p_stub_cb, (p_stub_cb) ? p_stub_cb->size: 0); + return -1; + } + + CMB_STUB_LOG_DBG( "[cmb_stub] registered, p_stub_cb:0x%p size(%d)\n", + p_stub_cb, p_stub_cb->size); + + cmb_stub_aif_ctrl_cb = p_stub_cb->aif_ctrl_cb; + cmb_stub_func_ctrl_cb = p_stub_cb->func_ctrl_cb; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_reg); + +/*! + * \brief A unregistration function for WMT-PLAT to unregister from CMB-STUB. + * + * An MTK-WCN-CMB-STUB unregistration function provided to WMT-PLAT to + * unregister itself and clear callback function references. + * + * \retval 0 operation success + */ +int +mtk_wcn_cmb_stub_unreg (void) +{ + cmb_stub_aif_ctrl_cb = NULL; + cmb_stub_func_ctrl_cb = NULL; + + CMB_STUB_LOG_INFO("[cmb_stub] unregistered \n"); /* KERN_DEBUG */ + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_unreg); + +/* stub functions for kernel to control audio path pin mux */ +int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + int ret; + + if ( (CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) { + + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl invalid (%d, %d)\n", state, ctrl); + return -1; + } + + /* avoid the early interrupt before we register the eirq_handler */ + if (cmb_stub_aif_ctrl_cb){ + ret = (*cmb_stub_aif_ctrl_cb)(state, ctrl); + CMB_STUB_LOG_INFO( "[cmb_stub] aif_ctrl_cb state(%d->%d) ctrl(%d) ret(%d)\n", + cmb_stub_aif_stat , state, ctrl, ret); /* KERN_DEBUG */ + + cmb_stub_aif_stat = state; + return ret; + } + else { + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null \n"); + return -2; + } +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_aif_ctrl); + +/* Use a temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X + * for ALPS backward compatible ONLY!!! Remove this table, related functions, + * and type definition after modifying other kernel built-in modules, such as + * AUDIO. [FixMe][GeorgeKuo] + */ +int +mt_combo_audio_ctrl_ex (COMBO_AUDIO_STATE state, u32 clt_ctrl) +{ + /* input sanity check */ + if (COMBO_AUDIO_STATE_MAX < state) { + CMB_STUB_LOG_WARN("[cmb_stub] invalid COMBO_AUDIO_STATE(%d)\n", state); + return -1; + } + + return mtk_wcn_cmb_stub_aif_ctrl(audio2aif[state], + (clt_ctrl) ? CMB_STUB_AIF_CTRL_EN : CMB_STUB_AIF_CTRL_DIS ); +} +EXPORT_SYMBOL(mt_combo_audio_ctrl_ex); + +void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on) { + if (cmb_stub_func_ctrl_cb) { + (*cmb_stub_func_ctrl_cb)(type, on); + } + else { + CMB_STUB_LOG_WARN("[cmb_stub] func_ctrl_cb null \n"); + } +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_func_ctrl); + +/*platform-related APIs*/ +//void clr_device_working_ability(UINT32 clockId, MT6573_STATE state); +//void set_device_working_ability(UINT32 clockId, MT6573_STATE state); + +static int +_mt_combo_plt_do_deep_idle(COMBO_IF src, int enter) { + int ret = -1; + + const char *combo_if_name[] = + { "COMBO_IF_UART", + "COMBO_IF_MSDC" + }; + + if(src != COMBO_IF_UART && src!= COMBO_IF_MSDC){ + CMB_STUB_LOG_WARN("src = %d is error\n", src); + return ret; + } + + if(src >= 0 && src < COMBO_IF_MAX){ + CMB_STUB_LOG_INFO("src = %s, to enter deep idle? %d \n", + combo_if_name[src], + enter); + } + + /*TODO: For Common SDIO configuration, we need to do some judgement between STP and WIFI + to decide if the msdc will enter deep idle safely*/ + + switch(src){ + case COMBO_IF_UART: + if(enter == 0){ + //clr_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); + //disable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); + } else { + //set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); + //enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); + } + ret = 0; + break; + + case COMBO_IF_MSDC: + if(enter == 0){ + //clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); + } else { + //set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); + } + ret = 0; + break; + + default: + ret = -1; + break; + } + + return ret; +} + +int +mt_combo_plt_enter_deep_idle ( + COMBO_IF src + ) { + //return 0; + // TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO + return _mt_combo_plt_do_deep_idle(src, 1); +} +EXPORT_SYMBOL(mt_combo_plt_enter_deep_idle); + +int +mt_combo_plt_exit_deep_idle ( + COMBO_IF src + ) { + //return 0; + // TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO + return _mt_combo_plt_do_deep_idle(src, 0); +} +EXPORT_SYMBOL(mt_combo_plt_exit_deep_idle); + diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c new file mode 100755 index 000000000000..d90b3198f863 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c @@ -0,0 +1,1012 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#if CONFIG_HAS_WAKELOCK +#include +#define CFG_WMT_WAKELOCK_SUPPORT 1 +#endif + + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/*header files*/ +#include +#include +#include + +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_exp.h" +#include "mtk_wcn_cmb_hw.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +#define GPIO_MT6620_PMUEN XXX +#define GPIO_MT6620_SYSRST XXX +#define GPIO_MT6620_LDO_EN XXX +#define INT_6620 XXX + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on); +static VOID wmt_plat_bgf_eirq_cb (VOID); + +static INT32 wmt_plat_ldo_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_pmu_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_rtc_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_rst_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_bgf_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_wifi_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_all_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_uart_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_pcm_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_i2s_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_sdio_pin_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_sync_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_lna_ctrl (ENUM_PIN_STATE state); + +static INT32 wmt_plat_dump_pin_conf (VOID); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT32 gWmtDbgLvl = WMT_LOG_INFO; + +unsigned int g_balance_flag; +spinlock_t g_balance_lock; +unsigned int g_bgf_irq = 69;//INT_6620;//bgf eint number +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + +#if CFG_WMT_WAKELOCK_SUPPORT +static OSAL_SLEEPABLE_LOCK gOsSLock; +static struct wake_lock wmtWakeLock; +#endif + +irq_cb wmt_plat_bgf_irq_cb = NULL; +device_audio_if_cb wmt_plat_audio_if_cb = NULL; +const static fp_set_pin gfp_set_pin_table[] = +{ + [PIN_LDO] = wmt_plat_ldo_ctrl, + [PIN_PMU] = wmt_plat_pmu_ctrl, + [PIN_RTC] = wmt_plat_rtc_ctrl, + [PIN_RST] = wmt_plat_rst_ctrl, + [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl, + [PIN_WIFI_EINT] = wmt_plat_wifi_eint_ctrl, + [PIN_ALL_EINT] = wmt_plat_all_eint_ctrl, + [PIN_UART_GRP] = wmt_plat_uart_ctrl, + [PIN_PCM_GRP] = wmt_plat_pcm_ctrl, + [PIN_I2S_GRP] = wmt_plat_i2s_ctrl, + [PIN_SDIO_GRP] = wmt_plat_sdio_pin_ctrl, + [PIN_GPS_SYNC] = wmt_plat_gps_sync_ctrl, + [PIN_GPS_LNA] = wmt_plat_gps_lna_ctrl, + +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief audio control callback function for CMB_STUB on ALPS + * + * A platform function required for dynamic binding with CMB_STUB on ALPS. + * + * \param state desired audio interface state to use + * \param flag audio interface control options + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval < 0 error for operation fail + */ +INT32 wmt_plat_audio_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + INT32 iRet = 0; + UINT32 pinShare; + + /* input sanity check */ + if ( (CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) { + iRet = -1; + WMT_ERR_FUNC("WMT-PLAT: invalid para, state(%d), ctrl(%d),iRet(%d) \n", state, ctrl, iRet); + return iRet; + } + if (0/*I2S/PCM share pin*/) { + // TODO: [FixMe][GeorgeKuo] how about MT6575? The following is applied to MT6573E1 only!! + pinShare = 1; + WMT_INFO_FUNC( "PCM/I2S pin share\n"); + } + else{ //E1 later + pinShare = 0; + WMT_INFO_FUNC( "PCM/I2S pin seperate\n"); + } + + iRet = 0; + + /* set host side first */ + switch (state) { + case CMB_STUB_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_1: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_2: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + case CMB_STUB_AIF_3: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + default: + /* FIXME: move to cust folder? */ + WMT_ERR_FUNC("invalid state [%d]\n", state); + return -1; + break; + } + + if (CMB_STUB_AIF_CTRL_EN == ctrl) { + WMT_INFO_FUNC("call chip aif setting \n"); + /* need to control chip side GPIO */ + //iRet += wmt_lib_set_aif(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + if (NULL != wmt_plat_audio_if_cb) + { + iRet += (*wmt_plat_audio_if_cb)(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + } + else + { + WMT_WARN_FUNC("wmt_plat_audio_if_cb is not registered \n"); + iRet -= 1; + } + } + else { + WMT_INFO_FUNC("skip chip aif setting \n"); + } + return iRet; + +} + +#if CFG_WMT_PS_SUPPORT +irqreturn_t irq_handler(int i, void *arg) +{ + wmt_plat_bgf_eirq_cb(); + return IRQ_HANDLED; +} +#endif + +static VOID +wmt_plat_bgf_eirq_cb (VOID) +{ + +#if CFG_WMT_PS_SUPPORT + //#error "need to disable EINT here" + //wmt_lib_ps_irq_cb(); + if (NULL != wmt_plat_bgf_irq_cb) + { + (*(wmt_plat_bgf_irq_cb))(); + } + else + { + WMT_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); + } +#else + return; +#endif +} + + + +VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb) +{ + wmt_plat_bgf_irq_cb = bgf_irq_cb; +} + +VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb) +{ + wmt_plat_audio_if_cb = aif_ctrl_cb; +} + + + + + + +INT32 +wmt_plat_init (P_PWR_SEQ_TIME pPwrSeqTime) +{ + //CMB_STUB_CB stub_cb; + /*PWR_SEQ_TIME pwr_seq_time;*/ + INT32 iret; + + //stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + //stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + //stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + //iret = mtk_wcn_cmb_stub_reg(&stub_cb); + + /* init cmb_hw */ + iret += mtk_wcn_cmb_hw_init(pPwrSeqTime); + + /*init wmt function ctrl wakelock if wake lock is supported by host platform*/ + #ifdef CFG_WMT_WAKELOCK_SUPPORT + wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl"); + osal_sleepable_lock_init(&gOsSLock); + #endif + + spin_lock_init(&g_balance_lock); + + WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} + + +INT32 +wmt_plat_deinit (VOID) +{ + INT32 iret; + + /* 1. de-init cmb_hw */ + iret = mtk_wcn_cmb_hw_deinit(); + /* 2. unreg to cmb_stub */ + iret += mtk_wcn_cmb_stub_unreg(); + /*3. wmt wakelock deinit*/ + #ifdef CFG_WMT_WAKELOCK_SUPPORT + wake_lock_destroy(&wmtWakeLock); + osal_sleepable_lock_deinit(&gOsSLock); + WMT_DBG_FUNC("destroy wmtWakeLock\n"); + #endif + WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} + +INT32 wmt_plat_sdio_ctrl (WMT_SDIO_SLOT_NUM sdioPortType, ENUM_FUNC_STATE on) +{ + if (FUNC_OFF == on) { + /* add control logic here to generate SDIO CARD REMOVAL event to mmc/sd + * controller. SDIO card removal operation and remove success messages + * are expected. + */ + } + else { + /* add control logic here to generate SDIO CARD INSERTION event to mmc/sd + * controller. SDIO card detection operation and detect success messages + * are expected. + */ + } + return 0; +} + +#if 0 +INT32 +wmt_plat_irq_ctrl ( + ENUM_FUNC_STATE state + ) +{ + return -1; +} +#endif + +static INT32 +wmt_plat_dump_pin_conf (VOID) +{ + WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration start<=\n"); + WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); + return 0; +} + + +INT32 wmt_plat_pwr_ctrl ( + ENUM_FUNC_STATE state + ) +{ + INT32 ret = -1; + + switch (state) { + case FUNC_ON: + // TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? + wmt_plat_dump_pin_conf(); + ret = mtk_wcn_cmb_hw_pwr_on(); + break; + + case FUNC_OFF: + ret = mtk_wcn_cmb_hw_pwr_off(); + break; + + case FUNC_RST: + ret = mtk_wcn_cmb_hw_rst(); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state); + break; + } + + return ret; +} + +INT32 wmt_plat_ps_ctrl (ENUM_FUNC_STATE state) +{ + return -1; +} + +INT32 +wmt_plat_eirq_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ) +{ + INT32 iRet; + unsigned int flags; + // TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls + + if ( (PIN_STA_INIT != state ) + && (PIN_STA_DEINIT != state ) + && (PIN_STA_EINT_EN != state ) + && (PIN_STA_EINT_DIS != state ) ) { + iRet = -1; + WMT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d), ret(%d) \n", state, id, iRet); + return iRet; + } + + iRet = -2; + switch (id) { + case PIN_BGF_EINT: + if (PIN_STA_INIT == state) { + /*request irq,low level triggered*/ + //iRet = request_irq(INT_6620, irq_handler, IRQF_TRIGGER_LOW | IRQF_DISABLED, "MTK6620_BT", NULL); + + + g_balance_flag = 1;//do not modify this value + WMT_INFO_FUNC("WMT-PLAT:BGFInt (init) \n"); + } + else if (PIN_STA_EINT_EN == state) { + /*enable irq*/ + spin_lock_irqsave(&g_balance_lock,flags); + if(g_balance_flag) + { + /*if enter this case, the bgf eint has been enabled,so skip it.*/ + WMT_INFO_FUNC("BGF_EINT has been enabled,g_balance_flag(%d)!\n",g_balance_flag); + } + else + { + /*do real irq enable implement is this case*/ + //enable_irq(INT_6620); + g_balance_flag++; + WMT_INFO_FUNC("WMT-PLAT:BGFInt (en),g_balance_flag(%d)\n",g_balance_flag); + } + spin_unlock_irqrestore(&g_balance_lock,flags); + } + else if (PIN_STA_EINT_DIS == state) { + /*disable irq*/ + spin_lock_irqsave(&g_balance_lock,flags); + if(!g_balance_flag) + { + /*if enter this case, the bgf eint has been disabled,so skip it.*/ + WMT_INFO_FUNC("BGF_EINT has been disabled,g_balance_flag(%d)!\n",g_balance_flag); + } + else + { + /*do real irq disable implement is this case*/ + //disable_irq_nosync(INT_6620); + g_balance_flag--; + WMT_INFO_FUNC("WMT-PLAT:BGFInt (dis) g_balance_flag(%d)\n",g_balance_flag); + } + spin_unlock_irqrestore(&g_balance_lock,flags); + } + else { + /* de-init: free irq*/ + //free_irq(INT_6620,NULL); + WMT_INFO_FUNC("WMT-PLAT:BGFInt (deinit) \n"); + + } + iRet = 0; + break; + + case PIN_ALL_EINT: +#if 0 + if (PIN_STA_INIT == state) { + + WMT_DBG_FUNC("WMT-PLAT:ALLInt (INIT but not used yet) \n"); + } + else if (PIN_STA_EINT_EN == state) { + WMT_DBG_FUNC("WMT-PLAT:ALLInt (EN but not used yet) \n"); + } + else if (PIN_STA_EINT_DIS == state) { + WMT_DBG_FUNC("WMT-PLAT:ALLInt (DIS but not used yet) \n"); + } + else { + + WMT_DBG_FUNC("WMT-PLAT:ALLInt (DEINIT but not used yet) \n"); + /* de-init: nothing to do in ALPS, such as un-registration... */ + } +#else + WMT_DBG_FUNC("WMT-PLAT:ALLInt (not used yet) \n"); +#endif + iRet = 0; + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl, ret (%d)\n", id, iRet); + iRet = -1; + break; + } + + return iRet; + +} + +INT32 wmt_plat_gpio_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ) +{ + if ( (PIN_ID_MAX > id) + && (PIN_STA_MAX > state) ) { + + // TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here + if (gfp_set_pin_table[id]) { + return (*(gfp_set_pin_table[id]))(state); /* .handler */ + } + else { + WMT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); + return -2; + } + } + WMT_ERR_FUNC("WMT-PLAT:[out of range] id(%d), state (%d)\n", id, state); + return -1; +} + +INT32 +wmt_plat_ldo_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + WMT_DBG_FUNC("WMT-PLAT:LDO init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + WMT_DBG_FUNC("WMT-PLAT:LDO (out 1) \n"); + break; + + case PIN_STA_OUT_L: + WMT_DBG_FUNC("WMT-PLAT:LDO (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:LDO deinit (in pd) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on LDO\n", state); + break; + } + return 0; +} + +INT32 +wmt_plat_pmu_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + + printk("WMT-PLAT:PMU init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + + printk("WMT-PLAT:PMU (out 1) \n"); + break; + + case PIN_STA_OUT_L: + + printk("WMT-PLAT:PMU (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + + printk("WMT-PLAT:PMU deinit (in pd) \n"); + break; + + default: + printk("WMT-PLAT:Warnning, invalid state(%d) on PMU\n", state); + break; + } + + return 0; +} + +INT32 +wmt_plat_rtc_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + WMT_DBG_FUNC("WMT-PLAT:RTC init \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RTC\n", state); + break; + } + return 0; +} + + +INT32 +wmt_plat_rst_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + + printk("WMT-PLAT:RST init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + + printk("WMT-PLAT:RST (out 1) \n"); + break; + + case PIN_STA_OUT_L: + + printk("WMT-PLAT:RST (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + + printk("WMT-PLAT:RST deinit (in pd) \n"); + break; + + default: + printk("WMT-PLAT:Warnning, invalid state(%d) on RST\n", state); + break; + } + + return 0; +} + +INT32 +wmt_plat_bgf_eint_ctrl ( + ENUM_PIN_STATE state + ) +{ + + switch(state) + { + case PIN_STA_INIT: + /*set to gpio input low, pull down eanble*/ + + WMT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd) \n"); + break; + + case PIN_STA_MUX: + /* first: set to EINT mode,interrupt input, pull up enable*/ + + WMT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint) \n"); + + /* second: enable bgf irq wake up host function*/ + do { + int iret; + //iret = enable_irq_wake(g_bgf_irq);//enable bgf irq wake up host function + //WMT_INFO_FUNC("enable_irq_wake(bgf:%d)++, ret(%d)\n", g_bgf_irq, iret); + } while (0); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /* first: disable bgf irq wake up host function*/ + do { + int iret; + //iret = disable_irq_wake(g_bgf_irq);//disable bgf irq wake up host function + if (iret) { + //WMT_WARN_FUNC("disable_irq_wake(bgf:%d) fail(%d)\n", g_bgf_irq, iret); + iret = 0; + } + else { + //WMT_INFO_FUNC("disable_irq_wake(bgf:%d)--, ret(%d)\n", g_bgf_irq, iret); + } + } while (0); + + /* second: set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state); + break; + } + + return 0; +} + + +INT32 wmt_plat_wifi_eint_ctrl(ENUM_PIN_STATE state) +{ +#if 0 + switch(state) + { + case PIN_STA_INIT: + break; + case PIN_STA_MUX: + + break; + case PIN_STA_EINT_EN: + break; + case PIN_STA_EINT_DIS: + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on WIFI EINT\n", state); + break; + } +#else + WMT_INFO_FUNC("WMT-PLAT:WIFI EINT is controlled by MSDC driver \n"); +#endif + return 0; +} + + +INT32 +wmt_plat_all_eint_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio input low, pull down eanble*/ + WMT_DBG_FUNC("WMT-PLAT:ALLInt init(in pd) \n"); + break; + + case PIN_STA_MUX: + /*set to gpio EINT mode, pull down enable*/ + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on ALL EINT\n", state); + break; + } + return 0; +} + +INT32 wmt_plat_uart_ctrl(ENUM_PIN_STATE state) +{ + switch(state) + { + case PIN_STA_MUX: + case PIN_STA_INIT: + WMT_DBG_FUNC("WMT-PLAT:UART init (mode_01, uart) \n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + WMT_DBG_FUNC("WMT-PLAT:UART deinit (out 0) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Group\n", state); + break; + } + + return 0; +} + + +INT32 wmt_plat_pcm_ctrl(ENUM_PIN_STATE state) +{ + switch(state) + { + case PIN_STA_MUX: + case PIN_STA_INIT: + /*set to PCM function*/ + WMT_DBG_FUNC("WMT-PLAT:PCM init (pcm) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + WMT_DBG_FUNC("WMT-PLAT:PCM deinit (out 0) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on PCM Group\n", state); + break; + } + return 0; +} + + +INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) +{ +#ifndef FM_ANALOG_INPUT + switch(state) + { + case PIN_STA_INIT: + case PIN_STA_MUX: + /*set to I2S function*/ + WMT_DBG_FUNC("WMT-PLAT:I2S init \n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0) \n"); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state); + break; + } +#else + WMT_INFO_FUNC( "[MT6620]warnning:FM analog mode is set, no I2S GPIO settings should be modified by combo driver\n"); +#endif + + return 0; +} + +INT32 +wmt_plat_sdio_pin_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + break; + case PIN_STA_DEINIT: + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on SDIO Group\n", state); + break; + } + return 0; +} + +static INT32 +wmt_plat_gps_sync_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + /*set GPS_SYNC GPIO to GPIO mode, pull disable,output low*/ + break; + + case PIN_STA_MUX: + /*set GPS_SYNC GPIO to GPS_SYNC function*/ + break; + + default: + break; + } + return 0; +} + + +static INT32 +wmt_plat_gps_lna_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/ + break; + case PIN_STA_OUT_H: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output high*/ + break; + case PIN_STA_OUT_L: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/ + break; + + default: + WMT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; + +} + + + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) +{ +#ifdef CFG_WMT_WAKELOCK_SUPPORT + static INT32 counter = 0; + + + osal_lock_sleepable_lock( &gOsSLock); + if (WL_OP_GET == opId) + { + ++counter; + }else if (WL_OP_PUT == opId) + { + --counter; + } + osal_unlock_sleepable_lock( &gOsSLock); + if (WL_OP_GET == opId && counter == 1) + { + wake_lock(&wmtWakeLock); + WMT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + + } + else if (WL_OP_PUT == opId && counter == 0) + { + wake_unlock(&wmtWakeLock); + WMT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + } + else + { + WMT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + } + return 0; +#else + WMT_WARN_FUNC("WMT-PLAT: host awake function is not supported."); + return 0; + +#endif +} + diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c new file mode 100755 index 000000000000..bcb1380189ed --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c @@ -0,0 +1,110 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#if CONFIG_HAS_WAKELOCK +#include +#define CFG_WMT_WAKELOCK_SUPPORT 1 +#endif + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/* ALPS and COMBO header files */ +#include + +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_plat_stub.h" +#include "wmt_exp.h" +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on) +{ + if (on) { + mtk_wcn_wmt_func_on((ENUM_WMTDRV_TYPE_T)type); + } + else { + mtk_wcn_wmt_func_off((ENUM_WMTDRV_TYPE_T)type); + } + return; +} + + +INT32 wmt_plat_stub_init (void) +{ + INT32 iRet = -1; + CMB_STUB_CB stub_cb; + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iRet = mtk_wcn_cmb_stub_reg(&stub_cb); + return iRet; +} + + diff --git a/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c new file mode 100755 index 000000000000..980ef5805881 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c @@ -0,0 +1,346 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CMB-HW]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal.h" +#include "mtk_wcn_cmb_hw.h" +#include "wmt_plat.h" +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define DFT_RTC_STABLE_TIME 100 +#define DFT_LDO_STABLE_TIME 100 +#define DFT_RST_STABLE_TIME 30 +#define DFT_OFF_STABLE_TIME 10 +#define DFT_ON_STABLE_TIME 30 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +PWR_SEQ_TIME gPwrSeqTime; + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 +mtk_wcn_cmb_hw_pwr_off (VOID) +{ + INT32 iRet = 0; + WMT_INFO_FUNC("CMB-HW, hw_pwr_off start\n"); + + /*1. disable irq --> should be done when do wmt-ic swDeinit period*/ + // TODO:[FixMe][GeorgeKuo] clarify this + + /*2. set bgf eint/all eint to deinit state, namely input low state*/ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ unregistered and set BGF_EINT GPIO to correct state!\n"); + /* 2.1 set ALL_EINT pin to correct state even it is not used currently */ + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, ALL_EINT IRQ unregistered and disabled\n"); + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_DEINIT); + /* 2.2 deinit gps sync */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT); + + /*3. set audio interface to CMB_STUB_AIF_0, BT PCM OFF, I2S OFF*/ + iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_0, CMB_STUB_AIF_CTRL_DIS); + + /*4. set control gpio into deinit state, namely input low state*/ + iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + + /*5. set uart tx/rx into deinit state, namely input low state*/ + iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_DEINIT); + + /* 6. Last, LDO output low */ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_L); + + /*7. deinit gps_lna*/ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT); + + WMT_INFO_FUNC("CMB-HW, hw_pwr_off finish\n"); + return iRet; +} + +INT32 +mtk_wcn_cmb_hw_pwr_on (VOID) +{ + static UINT32 _pwr_first_time = 1; + INT32 iRet = 0; + + WMT_INFO_FUNC("CMB-HW, hw_pwr_on start\n"); +#if 0 //IRQ should in inact state before power on, so this step is not needed + /* disable interrupt firstly */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); +#endif + /*set all control and eint gpio to init state, namely input low mode*/ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT); + // wmt_plat_gpio_ctrl(PIN_WIFI_EINT, PIN_STA_INIT); /* WIFI_EINT is controlled by SDIO host driver */ + // TODO: [FixMe][George]:WIFI_EINT is used in common SDIO + + /*1. pull high LDO to supply power to chip*/ + iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.ldoStableTime); + + /* 2. export RTC clock to chip*/ + if (_pwr_first_time) { + /* rtc clock should be output all the time, so no need to enable output again*/ + iRet += wmt_plat_gpio_ctrl(PIN_RTC, PIN_STA_INIT); + osal_msleep(gPwrSeqTime.rtcStableTime); + WMT_INFO_FUNC("CMB-HW, rtc clock exported\n"); + } + + /*3. set UART Tx/Rx to UART mode*/ + iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_INIT); + + /*4. PMU->output low, RST->output low, sleep off stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_msleep(gPwrSeqTime.offStableTime); + + /*5. PMU->output high, sleep rst stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.rstStableTime); + + /*6. RST->output high, sleep on stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.onStableTime); + + /*7. set audio interface to CMB_STUB_AIF_1, BT PCM ON, I2S OFF*/ + /* BT PCM bus default mode. Real control is done by audio */ + iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_1, CMB_STUB_AIF_CTRL_DIS); + + /*8. set EINT< -ommited-> move this to WMT-IC module, where common sdio interface will be identified and do proper operation*/ + // TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ registered and disabled \n"); + + /* 8.1 set ALL_EINT pin to correct state even it is not used currently */ + iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_MUX); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, hw_pwr_on finish (%d)\n", iRet); + + _pwr_first_time = 0; + return iRet; + +} + +INT32 +mtk_wcn_cmb_hw_rst (VOID) +{ + INT32 iRet = 0; + WMT_INFO_FUNC("CMB-HW, hw_rst start, eirq should be disabled before this step\n"); + + /*1. PMU->output low, RST->output low, sleep off stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_msleep(gPwrSeqTime.offStableTime); + + /*2. PMU->output high, sleep rst stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.rstStableTime); + + /*3. RST->output high, sleep on stable time*/ + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_msleep(gPwrSeqTime.onStableTime); + WMT_INFO_FUNC("CMB-HW, hw_rst finish, eirq should be enabled after this step\n"); + return 0; +} + +static VOID +mtk_wcn_cmb_hw_dmp_seq (VOID) +{ + PUINT32 pTimeSlot = (PUINT32)&gPwrSeqTime; + WMT_INFO_FUNC("combo chip power on sequence time, RTC (%d), LDO (%d), RST(%d), OFF(%d), ON(%d)\n", + pTimeSlot[0], /**pTimeSlot++,*/ + pTimeSlot[1], + pTimeSlot[2], + pTimeSlot[3], + pTimeSlot[4] + ); + return; +} + +INT32 +mtk_wcn_cmb_hw_init ( + P_PWR_SEQ_TIME pPwrSeqTime + ) +{ + if (NULL != pPwrSeqTime && + pPwrSeqTime->ldoStableTime > 0 && + pPwrSeqTime->rtcStableTime > 0 && + pPwrSeqTime->offStableTime > DFT_OFF_STABLE_TIME && + pPwrSeqTime->onStableTime > DFT_ON_STABLE_TIME && + pPwrSeqTime->rstStableTime > DFT_RST_STABLE_TIME + ) { + /*memcpy may be more performance*/ + WMT_DBG_FUNC("setting hw init sequence parameters\n"); + osal_memcpy(&gPwrSeqTime, pPwrSeqTime, osal_sizeof(gPwrSeqTime)); + } + else { + WMT_WARN_FUNC("invalid pPwrSeqTime parameter, use default hw init sequence parameters\n"); + gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME; + gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME; + gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME; + gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME; + gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME; + } + mtk_wcn_cmb_hw_dmp_seq(); + return 0; +} + +INT32 +mtk_wcn_cmb_hw_deinit (VOID) +{ + + WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit start, set to default hw init sequence parameters\n"); + gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME; + gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME; + gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME; + gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME; + gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME; + WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit finish\n"); + return 0; +} + diff --git a/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c new file mode 100755 index 000000000000..69546c061c29 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c @@ -0,0 +1,348 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CMB_STUB_LOG_INFO(fmt, arg...) printk(KERN_INFO fmt, ##arg) +#define CMB_STUB_LOG_WARN(fmt, arg...) printk(KERN_WARNING fmt, ##arg) +#define CMB_STUB_LOG_DBG(fmt, arg...) printk(KERN_DEBUG fmt, ##arg) + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +//#include +//#include /* clr_device_working_ability, MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE, MT65XX_PDN_PERI_MSDC2 */ +//#include +// TODO: [FixMe][GeorgeKuo] keep prototype unchanged temporarily. Replace it +// when integrate MT6628 & ALPS & other built-in modules, such as AUDIO. +//#include + +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb = NULL; +static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb = NULL; +static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0; + +/* A temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X. + * This is used for ALPS backward compatible ONLY!!! Remove this table, related + * functions, and type definition after modifying other kernel built-in modules, + * such as AUDIO. [FixMe][GeorgeKuo] + */ +static CMB_STUB_AIF_X audio2aif[] = { + [COMBO_AUDIO_STATE_0] = CMB_STUB_AIF_0, + [COMBO_AUDIO_STATE_1] = CMB_STUB_AIF_1, + [COMBO_AUDIO_STATE_2] = CMB_STUB_AIF_2, + [COMBO_AUDIO_STATE_3] = CMB_STUB_AIF_3, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief A registration function for WMT-PLAT to register itself to CMB-STUB. + * + * An MTK-WCN-CMB-STUB registration function provided to WMT-PLAT to register + * itself and related callback functions when driver being loaded into kernel. + * + * \param p_stub_cb a pointer carrying CMB_STUB_CB information + * + * \retval 0 operation success + * \retval -1 invalid parameters + */ +int +mtk_wcn_cmb_stub_reg (P_CMB_STUB_CB p_stub_cb) +{ + if ( (!p_stub_cb ) + || (p_stub_cb->size != sizeof(CMB_STUB_CB)) ) { + CMB_STUB_LOG_WARN( "[cmb_stub] invalid p_stub_cb:0x%p size(%d)\n", + p_stub_cb, (p_stub_cb) ? p_stub_cb->size: 0); + return -1; + } + + CMB_STUB_LOG_DBG( "[cmb_stub] registered, p_stub_cb:0x%p size(%d)\n", + p_stub_cb, p_stub_cb->size); + + cmb_stub_aif_ctrl_cb = p_stub_cb->aif_ctrl_cb; + cmb_stub_func_ctrl_cb = p_stub_cb->func_ctrl_cb; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_reg); + +/*! + * \brief A unregistration function for WMT-PLAT to unregister from CMB-STUB. + * + * An MTK-WCN-CMB-STUB unregistration function provided to WMT-PLAT to + * unregister itself and clear callback function references. + * + * \retval 0 operation success + */ +int +mtk_wcn_cmb_stub_unreg (void) +{ + cmb_stub_aif_ctrl_cb = NULL; + cmb_stub_func_ctrl_cb = NULL; + + CMB_STUB_LOG_INFO("[cmb_stub] unregistered \n"); /* KERN_DEBUG */ + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_unreg); + +/* stub functions for kernel to control audio path pin mux */ +int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + int ret; + + if ( (CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) { + + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl invalid (%d, %d)\n", state, ctrl); + return -1; + } + + /* avoid the early interrupt before we register the eirq_handler */ + if (cmb_stub_aif_ctrl_cb){ + ret = (*cmb_stub_aif_ctrl_cb)(state, ctrl); + CMB_STUB_LOG_INFO( "[cmb_stub] aif_ctrl_cb state(%d->%d) ctrl(%d) ret(%d)\n", + cmb_stub_aif_stat , state, ctrl, ret); /* KERN_DEBUG */ + + cmb_stub_aif_stat = state; + return ret; + } + else { + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null \n"); + return -2; + } +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_aif_ctrl); + +/* Use a temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X + * for ALPS backward compatible ONLY!!! Remove this table, related functions, + * and type definition after modifying other kernel built-in modules, such as + * AUDIO. [FixMe][GeorgeKuo] + */ +int +mt_combo_audio_ctrl_ex (COMBO_AUDIO_STATE state, u32 clt_ctrl) +{ + /* input sanity check */ + if (COMBO_AUDIO_STATE_MAX < state) { + CMB_STUB_LOG_WARN("[cmb_stub] invalid COMBO_AUDIO_STATE(%d)\n", state); + return -1; + } + + return mtk_wcn_cmb_stub_aif_ctrl(audio2aif[state], + (clt_ctrl) ? CMB_STUB_AIF_CTRL_EN : CMB_STUB_AIF_CTRL_DIS ); +} +EXPORT_SYMBOL(mt_combo_audio_ctrl_ex); + +void mtk_wcn_cmb_stub_func_ctrl (unsigned int type, unsigned int on) { + if (cmb_stub_func_ctrl_cb) { + (*cmb_stub_func_ctrl_cb)(type, on); + } + else { + CMB_STUB_LOG_WARN("[cmb_stub] func_ctrl_cb null \n"); + } +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_func_ctrl); + +/*platform-related APIs*/ +//void clr_device_working_ability(UINT32 clockId, MT6573_STATE state); +//void set_device_working_ability(UINT32 clockId, MT6573_STATE state); + +static int +_mt_combo_plt_do_deep_idle(COMBO_IF src, int enter) { + int ret = -1; + + const char *combo_if_name[] = + { "COMBO_IF_UART", + "COMBO_IF_MSDC" + }; + + if(src != COMBO_IF_UART && src!= COMBO_IF_MSDC){ + CMB_STUB_LOG_WARN("src = %d is error\n", src); + return ret; + } + + if(src >= 0 && src < COMBO_IF_MAX){ + CMB_STUB_LOG_INFO("src = %s, to enter deep idle? %d \n", + combo_if_name[src], + enter); + } + + /*TODO: For Common SDIO configuration, we need to do some judgement between STP and WIFI + to decide if the msdc will enter deep idle safely*/ + + switch(src){ + case COMBO_IF_UART: + if(enter == 0){ + //clr_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); + //disable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); + } else { + //set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); + //enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); + } + ret = 0; + break; + + case COMBO_IF_MSDC: + if(enter == 0){ + //clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); + } else { + //set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); + } + ret = 0; + break; + + default: + ret = -1; + break; + } + + return ret; +} + +int +mt_combo_plt_enter_deep_idle ( + COMBO_IF src + ) { + //return 0; + // TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO + return _mt_combo_plt_do_deep_idle(src, 1); +} +EXPORT_SYMBOL(mt_combo_plt_enter_deep_idle); + +int +mt_combo_plt_exit_deep_idle ( + COMBO_IF src + ) { + //return 0; + // TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO + return _mt_combo_plt_do_deep_idle(src, 0); +} +EXPORT_SYMBOL(mt_combo_plt_exit_deep_idle); + diff --git a/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c new file mode 100755 index 000000000000..73fe0982fbf3 --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c @@ -0,0 +1,1012 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* Copyright (c) 2009 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#if CONFIG_HAS_WAKELOCK +#include +#define CFG_WMT_WAKELOCK_SUPPORT 1 +#endif + + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/*header files*/ +#include +#include +#include + +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_exp.h" +#include "mtk_wcn_cmb_hw.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +#define GPIO_MT6620_PMUEN XXX +#define GPIO_MT6620_SYSRST XXX +#define GPIO_MT6620_LDO_EN XXX +#define INT_6620 XXX + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on); +static VOID wmt_plat_bgf_eirq_cb (VOID); + +static INT32 wmt_plat_ldo_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_pmu_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_rtc_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_rst_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_bgf_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_wifi_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_all_eint_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_uart_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_pcm_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_i2s_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_sdio_pin_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_sync_ctrl (ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_lna_ctrl (ENUM_PIN_STATE state); + +static INT32 wmt_plat_dump_pin_conf (VOID); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT32 gWmtDbgLvl = WMT_LOG_INFO; + +unsigned int g_balance_flag; +spinlock_t g_balance_lock; +unsigned int g_bgf_irq = INT_6620;//bgf eint number +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + +#if CFG_WMT_WAKELOCK_SUPPORT +static OSAL_SLEEPABLE_LOCK gOsSLock; +static struct wake_lock wmtWakeLock; +#endif + +irq_cb wmt_plat_bgf_irq_cb = NULL; +device_audio_if_cb wmt_plat_audio_if_cb = NULL; +const static fp_set_pin gfp_set_pin_table[] = +{ + [PIN_LDO] = wmt_plat_ldo_ctrl, + [PIN_PMU] = wmt_plat_pmu_ctrl, + [PIN_RTC] = wmt_plat_rtc_ctrl, + [PIN_RST] = wmt_plat_rst_ctrl, + [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl, + [PIN_WIFI_EINT] = wmt_plat_wifi_eint_ctrl, + [PIN_ALL_EINT] = wmt_plat_all_eint_ctrl, + [PIN_UART_GRP] = wmt_plat_uart_ctrl, + [PIN_PCM_GRP] = wmt_plat_pcm_ctrl, + [PIN_I2S_GRP] = wmt_plat_i2s_ctrl, + [PIN_SDIO_GRP] = wmt_plat_sdio_pin_ctrl, + [PIN_GPS_SYNC] = wmt_plat_gps_sync_ctrl, + [PIN_GPS_LNA] = wmt_plat_gps_lna_ctrl, + +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief audio control callback function for CMB_STUB on ALPS + * + * A platform function required for dynamic binding with CMB_STUB on ALPS. + * + * \param state desired audio interface state to use + * \param flag audio interface control options + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval < 0 error for operation fail + */ +INT32 wmt_plat_audio_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + INT32 iRet = 0; + UINT32 pinShare; + + /* input sanity check */ + if ( (CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) { + iRet = -1; + WMT_ERR_FUNC("WMT-PLAT: invalid para, state(%d), ctrl(%d),iRet(%d) \n", state, ctrl, iRet); + return iRet; + } + if (0/*I2S/PCM share pin*/) { + // TODO: [FixMe][GeorgeKuo] how about MT6575? The following is applied to MT6573E1 only!! + pinShare = 1; + WMT_INFO_FUNC( "PCM/I2S pin share\n"); + } + else{ //E1 later + pinShare = 0; + WMT_INFO_FUNC( "PCM/I2S pin seperate\n"); + } + + iRet = 0; + + /* set host side first */ + switch (state) { + case CMB_STUB_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_1: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_2: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + case CMB_STUB_AIF_3: + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + default: + /* FIXME: move to cust folder? */ + WMT_ERR_FUNC("invalid state [%d]\n", state); + return -1; + break; + } + + if (CMB_STUB_AIF_CTRL_EN == ctrl) { + WMT_INFO_FUNC("call chip aif setting \n"); + /* need to control chip side GPIO */ + //iRet += wmt_lib_set_aif(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + if (NULL != wmt_plat_audio_if_cb) + { + iRet += (*wmt_plat_audio_if_cb)(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + } + else + { + WMT_WARN_FUNC("wmt_plat_audio_if_cb is not registered \n"); + iRet -= 1; + } + } + else { + WMT_INFO_FUNC("skip chip aif setting \n"); + } + return iRet; + +} + +#if CFG_WMT_PS_SUPPORT +irqreturn_t irq_handler(int i, void *arg) +{ + wmt_plat_bgf_eirq_cb(); + return IRQ_HANDLED; +} +#endif + +static VOID +wmt_plat_bgf_eirq_cb (VOID) +{ + +#if CFG_WMT_PS_SUPPORT + //#error "need to disable EINT here" + //wmt_lib_ps_irq_cb(); + if (NULL != wmt_plat_bgf_irq_cb) + { + (*(wmt_plat_bgf_irq_cb))(); + } + else + { + WMT_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); + } +#else + return; +#endif +} + + + +VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb) +{ + wmt_plat_bgf_irq_cb = bgf_irq_cb; +} + +VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb) +{ + wmt_plat_audio_if_cb = aif_ctrl_cb; +} + + + + + + +INT32 +wmt_plat_init (P_PWR_SEQ_TIME pPwrSeqTime) +{ + //CMB_STUB_CB stub_cb; + /*PWR_SEQ_TIME pwr_seq_time;*/ + INT32 iret; + + //stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + //stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + //stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + //iret = mtk_wcn_cmb_stub_reg(&stub_cb); + + /* init cmb_hw */ + iret += mtk_wcn_cmb_hw_init(pPwrSeqTime); + + /*init wmt function ctrl wakelock if wake lock is supported by host platform*/ + #ifdef CFG_WMT_WAKELOCK_SUPPORT + wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl"); + osal_sleepable_lock_init(&gOsSLock); + #endif + + spin_lock_init(&g_balance_lock); + + WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} + + +INT32 +wmt_plat_deinit (VOID) +{ + INT32 iret; + + /* 1. de-init cmb_hw */ + iret = mtk_wcn_cmb_hw_deinit(); + /* 2. unreg to cmb_stub */ + iret += mtk_wcn_cmb_stub_unreg(); + /*3. wmt wakelock deinit*/ + #ifdef CFG_WMT_WAKELOCK_SUPPORT + wake_lock_destroy(&wmtWakeLock); + osal_sleepable_lock_deinit(&gOsSLock); + WMT_DBG_FUNC("destroy wmtWakeLock\n"); + #endif + WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} + +INT32 wmt_plat_sdio_ctrl (WMT_SDIO_SLOT_NUM sdioPortType, ENUM_FUNC_STATE on) +{ + if (FUNC_OFF == on) { + /* add control logic here to generate SDIO CARD REMOVAL event to mmc/sd + * controller. SDIO card removal operation and remove success messages + * are expected. + */ + } + else { + /* add control logic here to generate SDIO CARD INSERTION event to mmc/sd + * controller. SDIO card detection operation and detect success messages + * are expected. + */ + } + return 0; +} + +#if 0 +INT32 +wmt_plat_irq_ctrl ( + ENUM_FUNC_STATE state + ) +{ + return -1; +} +#endif + +static INT32 +wmt_plat_dump_pin_conf (VOID) +{ + WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration start<=\n"); + WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); + return 0; +} + + +INT32 wmt_plat_pwr_ctrl ( + ENUM_FUNC_STATE state + ) +{ + INT32 ret = -1; + + switch (state) { + case FUNC_ON: + // TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? + wmt_plat_dump_pin_conf(); + ret = mtk_wcn_cmb_hw_pwr_on(); + break; + + case FUNC_OFF: + ret = mtk_wcn_cmb_hw_pwr_off(); + break; + + case FUNC_RST: + ret = mtk_wcn_cmb_hw_rst(); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state); + break; + } + + return ret; +} + +INT32 wmt_plat_ps_ctrl (ENUM_FUNC_STATE state) +{ + return -1; +} + +INT32 +wmt_plat_eirq_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ) +{ + INT32 iRet; + unsigned int flags; + // TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls + + if ( (PIN_STA_INIT != state ) + && (PIN_STA_DEINIT != state ) + && (PIN_STA_EINT_EN != state ) + && (PIN_STA_EINT_DIS != state ) ) { + iRet = -1; + WMT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d), ret(%d) \n", state, id, iRet); + return iRet; + } + + iRet = -2; + switch (id) { + case PIN_BGF_EINT: + if (PIN_STA_INIT == state) { + /*request irq,low level triggered*/ + iRet = request_irq(INT_6620, irq_handler, IRQF_TRIGGER_LOW | IRQF_DISABLED, "MTK6620_BT", NULL); + + + g_balance_flag = 1;//do not modify this value + WMT_INFO_FUNC("WMT-PLAT:BGFInt (init) \n"); + } + else if (PIN_STA_EINT_EN == state) { + /*enable irq*/ + spin_lock_irqsave(&g_balance_lock,flags); + if(g_balance_flag) + { + /*if enter this case, the bgf eint has been enabled,so skip it.*/ + WMT_INFO_FUNC("BGF_EINT has been enabled,g_balance_flag(%d)!\n",g_balance_flag); + } + else + { + /*do real irq enable implement is this case*/ + enable_irq(INT_6620); + g_balance_flag++; + WMT_INFO_FUNC("WMT-PLAT:BGFInt (en),g_balance_flag(%d)\n",g_balance_flag); + } + spin_unlock_irqrestore(&g_balance_lock,flags); + } + else if (PIN_STA_EINT_DIS == state) { + /*disable irq*/ + spin_lock_irqsave(&g_balance_lock,flags); + if(!g_balance_flag) + { + /*if enter this case, the bgf eint has been disabled,so skip it.*/ + WMT_INFO_FUNC("BGF_EINT has been disabled,g_balance_flag(%d)!\n",g_balance_flag); + } + else + { + /*do real irq disable implement is this case*/ + disable_irq_nosync(INT_6620); + g_balance_flag--; + WMT_INFO_FUNC("WMT-PLAT:BGFInt (dis) g_balance_flag(%d)\n",g_balance_flag); + } + spin_unlock_irqrestore(&g_balance_lock,flags); + } + else { + /* de-init: free irq*/ + free_irq(INT_6620,NULL); + WMT_INFO_FUNC("WMT-PLAT:BGFInt (deinit) \n"); + + } + iRet = 0; + break; + + case PIN_ALL_EINT: +#if 0 + if (PIN_STA_INIT == state) { + + WMT_DBG_FUNC("WMT-PLAT:ALLInt (INIT but not used yet) \n"); + } + else if (PIN_STA_EINT_EN == state) { + WMT_DBG_FUNC("WMT-PLAT:ALLInt (EN but not used yet) \n"); + } + else if (PIN_STA_EINT_DIS == state) { + WMT_DBG_FUNC("WMT-PLAT:ALLInt (DIS but not used yet) \n"); + } + else { + + WMT_DBG_FUNC("WMT-PLAT:ALLInt (DEINIT but not used yet) \n"); + /* de-init: nothing to do in ALPS, such as un-registration... */ + } +#else + WMT_DBG_FUNC("WMT-PLAT:ALLInt (not used yet) \n"); +#endif + iRet = 0; + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl, ret (%d)\n", id, iRet); + iRet = -1; + break; + } + + return iRet; + +} + +INT32 wmt_plat_gpio_ctrl ( + ENUM_PIN_ID id, + ENUM_PIN_STATE state + ) +{ + if ( (PIN_ID_MAX > id) + && (PIN_STA_MAX > state) ) { + + // TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here + if (gfp_set_pin_table[id]) { + return (*(gfp_set_pin_table[id]))(state); /* .handler */ + } + else { + WMT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); + return -2; + } + } + WMT_ERR_FUNC("WMT-PLAT:[out of range] id(%d), state (%d)\n", id, state); + return -1; +} + +INT32 +wmt_plat_ldo_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + WMT_DBG_FUNC("WMT-PLAT:LDO init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + WMT_DBG_FUNC("WMT-PLAT:LDO (out 1) \n"); + break; + + case PIN_STA_OUT_L: + WMT_DBG_FUNC("WMT-PLAT:LDO (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:LDO deinit (in pd) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on LDO\n", state); + break; + } + return 0; +} + +INT32 +wmt_plat_pmu_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + + printk("WMT-PLAT:PMU init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + + printk("WMT-PLAT:PMU (out 1) \n"); + break; + + case PIN_STA_OUT_L: + + printk("WMT-PLAT:PMU (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + + printk("WMT-PLAT:PMU deinit (in pd) \n"); + break; + + default: + printk("WMT-PLAT:Warnning, invalid state(%d) on PMU\n", state); + break; + } + + return 0; +} + +INT32 +wmt_plat_rtc_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + WMT_DBG_FUNC("WMT-PLAT:RTC init \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RTC\n", state); + break; + } + return 0; +} + + +INT32 +wmt_plat_rst_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio output low, disable pull*/ + + printk("WMT-PLAT:RST init (out 0) \n"); + break; + + case PIN_STA_OUT_H: + + printk("WMT-PLAT:RST (out 1) \n"); + break; + + case PIN_STA_OUT_L: + + printk("WMT-PLAT:RST (out 0) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + + printk("WMT-PLAT:RST deinit (in pd) \n"); + break; + + default: + printk("WMT-PLAT:Warnning, invalid state(%d) on RST\n", state); + break; + } + + return 0; +} + +INT32 +wmt_plat_bgf_eint_ctrl ( + ENUM_PIN_STATE state + ) +{ + + switch(state) + { + case PIN_STA_INIT: + /*set to gpio input low, pull down eanble*/ + + WMT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd) \n"); + break; + + case PIN_STA_MUX: + /* first: set to EINT mode,interrupt input, pull up enable*/ + + WMT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint) \n"); + + /* second: enable bgf irq wake up host function*/ + do { + int iret; + iret = enable_irq_wake(g_bgf_irq);//enable bgf irq wake up host function + WMT_INFO_FUNC("enable_irq_wake(bgf:%d)++, ret(%d)\n", g_bgf_irq, iret); + } while (0); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /* first: disable bgf irq wake up host function*/ + do { + int iret; + iret = disable_irq_wake(g_bgf_irq);//disable bgf irq wake up host function + if (iret) { + WMT_WARN_FUNC("disable_irq_wake(bgf:%d) fail(%d)\n", g_bgf_irq, iret); + iret = 0; + } + else { + WMT_INFO_FUNC("disable_irq_wake(bgf:%d)--, ret(%d)\n", g_bgf_irq, iret); + } + } while (0); + + /* second: set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state); + break; + } + + return 0; +} + + +INT32 wmt_plat_wifi_eint_ctrl(ENUM_PIN_STATE state) +{ +#if 0 + switch(state) + { + case PIN_STA_INIT: + break; + case PIN_STA_MUX: + + break; + case PIN_STA_EINT_EN: + break; + case PIN_STA_EINT_DIS: + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on WIFI EINT\n", state); + break; + } +#else + WMT_INFO_FUNC("WMT-PLAT:WIFI EINT is controlled by MSDC driver \n"); +#endif + return 0; +} + + +INT32 +wmt_plat_all_eint_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch(state) + { + case PIN_STA_INIT: + /*set to gpio input low, pull down eanble*/ + WMT_DBG_FUNC("WMT-PLAT:ALLInt init(in pd) \n"); + break; + + case PIN_STA_MUX: + /*set to gpio EINT mode, pull down enable*/ + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on ALL EINT\n", state); + break; + } + return 0; +} + +INT32 wmt_plat_uart_ctrl(ENUM_PIN_STATE state) +{ + switch(state) + { + case PIN_STA_MUX: + case PIN_STA_INIT: + WMT_DBG_FUNC("WMT-PLAT:UART init (mode_01, uart) \n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + WMT_DBG_FUNC("WMT-PLAT:UART deinit (out 0) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Group\n", state); + break; + } + + return 0; +} + + +INT32 wmt_plat_pcm_ctrl(ENUM_PIN_STATE state) +{ + switch(state) + { + case PIN_STA_MUX: + case PIN_STA_INIT: + /*set to PCM function*/ + WMT_DBG_FUNC("WMT-PLAT:PCM init (pcm) \n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + WMT_DBG_FUNC("WMT-PLAT:PCM deinit (out 0) \n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on PCM Group\n", state); + break; + } + return 0; +} + + +INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) +{ +#ifndef FM_ANALOG_INPUT + switch(state) + { + case PIN_STA_INIT: + case PIN_STA_MUX: + /*set to I2S function*/ + WMT_DBG_FUNC("WMT-PLAT:I2S init \n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable*/ + WMT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0) \n"); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state); + break; + } +#else + WMT_INFO_FUNC( "[MT6620]warnning:FM analog mode is set, no I2S GPIO settings should be modified by combo driver\n"); +#endif + + return 0; +} + +INT32 +wmt_plat_sdio_pin_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + break; + case PIN_STA_DEINIT: + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on SDIO Group\n", state); + break; + } + return 0; +} + +static INT32 +wmt_plat_gps_sync_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + /*set GPS_SYNC GPIO to GPIO mode, pull disable,output low*/ + break; + + case PIN_STA_MUX: + /*set GPS_SYNC GPIO to GPS_SYNC function*/ + break; + + default: + break; + } + return 0; +} + + +static INT32 +wmt_plat_gps_lna_ctrl ( + ENUM_PIN_STATE state + ) +{ + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/ + break; + case PIN_STA_OUT_H: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output high*/ + break; + case PIN_STA_OUT_L: + /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/ + break; + + default: + WMT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; + +} + + + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) +{ +#ifdef CFG_WMT_WAKELOCK_SUPPORT + static INT32 counter = 0; + + + osal_lock_sleepable_lock( &gOsSLock); + if (WL_OP_GET == opId) + { + ++counter; + }else if (WL_OP_PUT == opId) + { + --counter; + } + osal_unlock_sleepable_lock( &gOsSLock); + if (WL_OP_GET == opId && counter == 1) + { + wake_lock(&wmtWakeLock); + WMT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + + } + else if (WL_OP_PUT == opId && counter == 0) + { + wake_unlock(&wmtWakeLock); + WMT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + } + else + { + WMT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter); + } + return 0; +#else + WMT_WARN_FUNC("WMT-PLAT: host awake function is not supported."); + return 0; + +#endif +} + diff --git a/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c new file mode 100755 index 000000000000..bcb1380189ed --- /dev/null +++ b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c @@ -0,0 +1,110 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#if CONFIG_HAS_WAKELOCK +#include +#define CFG_WMT_WAKELOCK_SUPPORT 1 +#endif + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/* ALPS and COMBO header files */ +#include + +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_plat_stub.h" +#include "wmt_exp.h" +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on) +{ + if (on) { + mtk_wcn_wmt_func_on((ENUM_WMTDRV_TYPE_T)type); + } + else { + mtk_wcn_wmt_func_off((ENUM_WMTDRV_TYPE_T)type); + } + return; +} + + +INT32 wmt_plat_stub_init (void) +{ + INT32 iRet = -1; + CMB_STUB_CB stub_cb; + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iRet = mtk_wcn_cmb_stub_reg(&stub_cb); + return iRet; +} + + diff --git a/drivers/mtk_wcn_combo/drv_bt/Makefile b/drivers/mtk_wcn_combo/drv_bt/Makefile new file mode 100755 index 000000000000..9cd070acd71a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_bt/Makefile @@ -0,0 +1,43 @@ +# Copyright Statement: +# +# This software/firmware and related documentation ("MediaTek Software") are +# protected under relevant copyright laws. The information contained herein +# is confidential and proprietary to MediaTek Inc. and/or its licensors. +# Without the prior written permission of MediaTek inc. and/or its licensors, +# any reproduction, modification, use or disclosure of MediaTek Software, +# and information contained herein, in whole or in part, shall be strictly prohibited. +# +# MediaTek Inc. (C) 2010. All rights reserved. +# +# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON +# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH +# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES +# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES +# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK +# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR +# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND +# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO +# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +# +# The following software/firmware and/or related documentation ("MediaTek Software") +# have been modified by MediaTek Inc. All revisions are subject to any receiver's +# applicable license agreements with MediaTek Inc. + + +# +# Makefile for the Linux Bluetooth HCI device drivers. +# +ccflags-y := -I$(src)/include -I$(src)/../common/include -I$(src)/../common/linux/include + +obj-$(CONFIG_MTK_COMBO_BT_HCI) += hci_stp.o +hci_stp-objs := linux/hci_stp.o + diff --git a/drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h b/drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h new file mode 100755 index 000000000000..248fcf135911 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h @@ -0,0 +1,45 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +static struct btradio_conf_data sDefaultCfg = +{ + {0x00, 0x00, 0x46, 0x66, 0x20, 0x01}, + {0x60, 0x00}, + {0x23, 0x10, 0x00, 0x00}, + {0x06, 0x80, 0x00, 0x06, 0x03, 0x06}, + {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04}, + {0x80, 0x00}, + {0xFF, 0xFF, 0xFF} +}; \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h b/drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h new file mode 100755 index 000000000000..cff49c1529ef --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h @@ -0,0 +1,172 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein is + * confidential and proprietary to MediaTek Inc. and/or its licensors. Without + * the prior written permission of MediaTek inc. and/or its licensors, any + * reproduction, modification, use or disclosure of MediaTek Software, and + * information contained herein, in whole or in part, shall be strictly + * prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER + * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL + * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH + * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, + * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES + * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. + * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO + * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK + * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE + * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S + * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE + * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE + * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE + * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek + * Software") have been modified by MediaTek Inc. All revisions are subject to + * any receiver's applicable license agreements with MediaTek Inc. + */ + + +#ifndef _HCI_STP_H +#define _HCI_STP_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* debugging */ +#include +#include + +/* constant of kernel version */ +#include + +/* kthread APIs */ +#include + +#include +#include + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#define HCI_STP_TX_TASKLET (0) /* do tx in a tasklet context */ +#define HCI_STP_TX_THRD (1) /* do tx in an init thread context */ +/* select tx context */ +#define HCI_STP_TX (HCI_STP_TX_THRD) + + +#if (HCI_STP_TX == HCI_STP_TX_TASKLET) +#define HCI_STP_TX_TASKLET_RWLOCK (0) /* use rwlock_t */ +#define HCI_STP_TX_TASKLET_SPINLOCK (1) /* use spinlock_t */ +/* select txq protection method */ +#define HCI_STP_TX_TASKLET_LOCK (HCI_STP_TX_TASKLET_SPINLOCK) +#endif + +/* Flag to enable BD address auto-gen mechanism */ +/* Auto-gen address is illegal, default disabled */ +#define BD_ADDR_AUTOGEN (0) + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* HCI-STP flag bits */ +#define HCI_STP_PROTO_SET (0) +/* HCI-STP flag TX states bits */ +#define HCI_STP_SENDING (1) +#define HCI_STP_TX_WAKEUP (2) + +/* maximum delay required, shall also consider possible delay on a busy system. */ +#define BT_CMD_DELAY_MS_COMM (100) /*(50)*/ +#define BT_CMD_DELAY_MS_RESET (600) /*(500)*/ + +#define BT_CMD_DELAY_SAFE_GUARD (20) /*(2)*/ + +/* HCI-STP safer hci_reset handling */ +#define HCI_STP_SAFE_RESET (1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct hci_stp_init_cmd { + unsigned char *hci_cmd; + unsigned int cmdSz; + unsigned char *hci_evt; + unsigned int evtSz; + char *str; +}; + +struct hci_stp { + struct hci_dev *hdev; + unsigned long flags; + + struct sk_buff_head txq; /* used to queue TX packets */ + unsigned long tx_state; + + struct work_struct init_work; + struct completion *p_init_comp; + wait_queue_head_t *p_init_evt_wq; + spinlock_t init_lock; /* protect init variables: comp and wq */ + unsigned int init_cmd_idx; + int init_evt_rx_flag; /* init result of last sent cmd */ + +#if HCI_STP_SAFE_RESET + wait_queue_head_t reset_wq; + atomic_t reset_count; /* !0: reset in progress */ +#endif + //void *priv; /* unused? */ + //struct sk_buff *tx_skb; /* unused? */ + //spinlock_t rx_lock; /* unused? */ +}; + +struct btradio_conf_data { + unsigned char addr[6]; + unsigned char voice[2]; + unsigned char codec[4]; + unsigned char radio[6]; + unsigned char sleep[7]; + unsigned char feature[2]; + unsigned char tx_pwr_offset[3]; +}; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define hci_stp_init_entry(c) \ + {.hci_cmd=c, .cmdSz=sizeof(c), .hci_evt=c##_evt, .evtSz=sizeof(c##_evt), .str=#c} + +#endif /* end of _HCI_STP_H */ + diff --git a/drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c b/drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c new file mode 100755 index 000000000000..30d400ae719c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c @@ -0,0 +1,1589 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein is + * confidential and proprietary to MediaTek Inc. and/or its licensors. Without + * the prior written permission of MediaTek inc. and/or its licensors, any + * reproduction, modification, use or disclosure of MediaTek Software, and + * information contained herein, in whole or in part, shall be strictly + * prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER + * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL + * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH + * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, + * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES + * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. + * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO + * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK + * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE + * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S + * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE + * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE + * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE + * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek + * Software") have been modified by MediaTek Inc. All revisions are subject to + * any receiver's applicable license agreements with MediaTek Inc. + */ + + +#include "hci_stp.h" +#include "bt_conf.h" +#include "stp_exp.h" +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Debugging Purpose */ +#define PFX "[HCI-STP]" +#define BT_LOG_LOUD (4) +#define BT_LOG_DBG (3) +#define BT_LOG_INFO (2) +#define BT_LOG_WARN (1) +#define BT_LOG_ERR (0) + +#define VERSION "2.0" + +/* H4 receiver States */ +#define H4_W4_PACKET_TYPE (0) +#define H4_W4_EVENT_HDR (1) +#define H4_W4_ACL_HDR (2) +#define H4_W4_SCO_HDR (3) +#define H4_W4_DATA (4) + +#define HCI_STP_TXQ_IN_BLZ (0) +/* access txq in BlueZ tx tasklet context */ +#define HCI_STP_TXQ_IN_HCISTP (1) +/* access txq in HCI-STP context, defined by compile flag: HCI_STP_TX */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +unsigned int gDbgLevel = BT_LOG_INFO; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +/* Allow one BT driver */ +static struct hci_dev *hdev = NULL; +static int reset = 0; + +/* maybe struct hci_stp is a better place to put these data */ +#if (HCI_STP_TX == HCI_STP_TX_TASKLET) +static struct tasklet_struct hci_tx_tasklet; + +#if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) +static DEFINE_RWLOCK(hci_stp_txqlock); + +#elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) +static spinlock_t hci_stp_txqlock; + +#endif +#endif + +#if (HCI_STP_TX == HCI_STP_TX_THRD) +static spinlock_t hci_stp_txqlock; +struct task_struct * hci_stp_tx_thrd = NULL; +wait_queue_head_t hci_stp_tx_thrd_wq; +#endif + + +#define CUSTOM_BT_CFG_FILE "/data/BT.cfg" +#define INTERNAL_BT_CFG_FILE "/data/bluetooth/BT.cfg" + +static bool fgetEFUSE = false; + +static unsigned char bt_get_bd_addr[4] = + {0x01, 0x09, 0x10, 0x00}; +static unsigned char bt_get_bd_addr_evt[] = + {0x04, 0x0E, 0x0A, 0x01, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static unsigned char bt_set_bd_addr[10] = + {0x01, 0x1A, 0xFC, 0x06, 0x01, 0x20, 0x66, 0x46, 0x00, 0x00}; +static unsigned char bt_set_bd_addr_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x1A, 0xFC, 0x00}; +static unsigned char bt_set_link_key_type[5]= + {0x01, 0x1B, 0xFC, 0x01, 0x01}; +static unsigned char bt_set_link_key_type_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x1B, 0xFC, 0x00}; +static unsigned char bt_set_unit_key[20] = + {0x01, 0x75, 0xFC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static unsigned char bt_set_unit_key_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x75, 0xFC, 0x00}; +static unsigned char bt_set_encrypt[7] = + {0x01, 0x76, 0xFC, 0x03, 0x00, 0x02, 0x10}; +static unsigned char bt_set_encrypt_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x76, 0xFC, 0x00}; +static unsigned char bt_set_pin_code_type[5] = + {0x01, 0x0A, 0x0C, 0x01, 0x00}; +static unsigned char bt_set_pin_code_type_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x0A, 0x0C, 0x00}; +static unsigned char bt_set_voice[6] = + {0x01, 0x26, 0x0C, 0x02, 0x60, 0x00}; +static unsigned char bt_set_voice_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x26, 0x0C, 0x00}; +static unsigned char bt_set_codec[8] = + {0x01, 0x72, 0xFC, 0x04, 0x23, 0x10, 0x00, 0x00}; +static unsigned char bt_set_codec_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x72, 0xFC, 0x00}; +static unsigned char bt_set_radio[10] = + {0x01, 0x79, 0xFC, 0x06, 0x06, 0x80, 0x00, 0x06, 0x03, 0x06}; +static unsigned char bt_set_radio_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x79, 0xFC, 0x00}; +static unsigned char bt_set_tx_pwr_offset[7] = + {0x01, 0x93, 0xFC, 0x03, 0xFF, 0xFF, 0xFF}; +static unsigned char bt_set_tx_pwr_offset_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x93, 0xFC, 0x00}; +static unsigned char bt_set_sleep[11] = + {0x01, 0x7A, 0xFC, 0x07, 0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04}; +static unsigned char bt_set_sleep_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x7A, 0xFC, 0x00}; +static unsigned char bt_set_feature[6] = + {0x01, 0x7D, 0xFC, 0x02, 0x80, 0x0}; +static unsigned char bt_set_feature_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x7D, 0xFC, 0x00}; +static unsigned char bt_set_OSC[9] = + {0x01, 0x7B, 0xFC, 0x05, 0x01, 0x01, 0x14, 0x0A, 0x05}; +static unsigned char bt_set_OSC_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x7B, 0xFC, 0x00}; +static unsigned char bt_set_LPO[14] = + {0x01, 0x7C, 0xFC, 0x0A, 0x01, 0xFA, 0x0A, 0x02, 0x00, 0xA6, 0x0E, 0x00, 0x40, 0x00}; +static unsigned char bt_set_LPO_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x7C, 0xFC, 0x00}; +static unsigned char bt_set_legacy_PTA[14] = + {0x01, 0x74, 0xFC, 0x0A, 0xC9, 0x8B, 0xBF, 0x00, 0x00, 0x52, 0x0E, 0x0E, 0x1F, 0x1B}; +static unsigned char bt_set_legacy_PTA_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x74, 0xFC, 0x00}; +static unsigned char bt_set_BLE_PTA[9] = + {0x01, 0xFC, 0xFC, 0x05, 0x16, 0x0E, 0x0E, 0x00, 0x07}; +static unsigned char bt_set_BLE_PTA_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xFC, 0xFC, 0x00}; +static unsigned char bt_set_RF_desence[10] = + {0x01, 0x20, 0xFC, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; +static unsigned char bt_set_RF_desence_evt[] = + {0x04, 0x0e, 0x04, 0x01, 0x20, 0xFC, 0x00}; +static unsigned char bt_reset[4] = + {0x01, 0x03, 0x0C, 0x0}; +static unsigned char bt_reset_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0x03, 0x0C, 0x00}; +static unsigned char bt_set_intern_PTA_1[19] = + {0x01, 0xFB, 0xFC, 0x0F, 0x00, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x02, 0x01}; +static unsigned char bt_set_intern_PTA_1_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xFB, 0xFC, 0x00}; +static unsigned char bt_set_intern_PTA_2[11] = + {0x01, 0xFB, 0xFC, 0x07, 0x01, 0x19, 0x19, 0x07, 0xD0, 0x00, 0x01}; +static unsigned char bt_set_intern_PTA_2_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xFB, 0xFC, 0x00}; +static unsigned char bt_set_SLP_control_reg[12] = + {0x01, 0xD0, 0xFC, 0x08, 0x74, 0x00, 0x01, 0x81, 0xE2, 0x29, 0x0, 0x0}; +static unsigned char bt_set_SLP_control_reg_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xD0, 0xFC, 0x00}; +static unsigned char bt_set_SLP_LDOD_reg[12] = + {0x01, 0xD0, 0xFC, 0x08, 0x1C, 0x00, 0x02, 0x81, 0x79, 0x08, 0x0, 0x0}; +static unsigned char bt_set_SLP_LDOD_reg_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xD0, 0xFC, 0x00}; +static unsigned char bt_set_RF_reg_100[10] = + {0x01, 0xB0, 0xFC, 0x06, 0x64, 0x01, 0x02, 0x00, 0x00, 0x00}; +static unsigned char bt_set_RF_reg_100_evt[] = + {0x04, 0x0E, 0x04, 0x01, 0xB0, 0xFC, 0x00}; + +/* Do init commands in sequence, cmd and cmd##_evt */ +static struct hci_stp_init_cmd init_table[] = +{ + hci_stp_init_entry(bt_get_bd_addr), + hci_stp_init_entry(bt_set_bd_addr), + hci_stp_init_entry(bt_set_link_key_type), + hci_stp_init_entry(bt_set_unit_key), + hci_stp_init_entry(bt_set_encrypt), + hci_stp_init_entry(bt_set_pin_code_type), + hci_stp_init_entry(bt_set_voice), + hci_stp_init_entry(bt_set_codec), + hci_stp_init_entry(bt_set_radio), + hci_stp_init_entry(bt_set_tx_pwr_offset), + hci_stp_init_entry(bt_set_sleep), + hci_stp_init_entry(bt_set_feature), + hci_stp_init_entry(bt_set_OSC), + hci_stp_init_entry(bt_set_LPO), + hci_stp_init_entry(bt_set_legacy_PTA), + hci_stp_init_entry(bt_set_BLE_PTA), + hci_stp_init_entry(bt_set_RF_desence), + hci_stp_init_entry(bt_reset), + hci_stp_init_entry(bt_set_intern_PTA_1), + hci_stp_init_entry(bt_set_intern_PTA_2), + hci_stp_init_entry(bt_set_SLP_control_reg), + hci_stp_init_entry(bt_set_SLP_LDOD_reg), + hci_stp_init_entry(bt_set_RF_reg_100), +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define BT_LOUD_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_LOUD){printk(PFX "[L]%s:" fmt, __FUNCTION__ ,##arg);} +#define BT_DBG_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_DBG){printk(PFX "[D]%s:" fmt, __FUNCTION__ ,##arg);} +#define BT_INFO_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_INFO){printk(PFX "[I]%s:" fmt, __FUNCTION__ ,##arg);} +#define BT_WARN_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_WARN){printk(PFX "[W]%s:" fmt, __FUNCTION__ ,##arg);} +#define BT_ERR_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_ERR){printk(PFX "[E]%s:" fmt, __FUNCTION__ ,##arg);} +#define BT_TRC_FUNC(f) if(gDbgLevel >= BT_LOG_LOUD){printk(PFX "[T]%s:%d\n", __FUNCTION__, __LINE__);} + +#if HCI_STP_SAFE_RESET +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) +/* HCI_RESET bit definition in linux/include/net/bluetooth/hci.h since 2.6.39: + http://lxr.free-electrons.com/source/include/net/bluetooth/hci.h?v=2.6.39;a=arm +*/ +#define BT_GET_HDEV_RST_FG(hdev) (test_bit(HCI_RESET, &hdev->flags)) +#else +#define BT_GET_HDEV_RST_FG(hdev) (0) /* no HCI_RESET bit available */ +#endif +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Functions to be implemted by all HCI_STP_TX_* methods */ +void hci_stp_tx_init (struct hci_stp *hu); +void hci_stp_tx_deinit (struct hci_stp *hu); +void hci_stp_txq_lock (unsigned int ctx); +void hci_stp_txq_unlock (unsigned int ctx); +void hci_stp_tx_kick (void); + +/* Functions to be implemented by all HCI_STP_INIT_* methods*/ +static int hci_stp_dev_init (struct hci_stp *phu); + +#if (HCI_STP_TX == HCI_STP_TX_TASKLET) +static int hci_stp_tx_wakeup (struct hci_stp *hu); +static void hci_stp_tx_tasklet_func (unsigned long data); +#endif + +#if (HCI_STP_TX == HCI_STP_TX_THRD) +static int hci_stp_tx_thrd_func (void *pdata); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static ssize_t file_read(char *filename, char *buf, size_t len, loff_t *offset) +{ + struct file *fp; + mm_segment_t old_fs; + ssize_t retLen; + + fp = filp_open(filename, O_RDONLY, 0); + if (IS_ERR(fp)) { + BT_WARN_FUNC("Failed to open %s!\n", filename); + return -1; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if ((fp->f_op == NULL) || (fp->f_op->read == NULL)){ + BT_WARN_FUNC("File can not be read!\n"); + set_fs(old_fs); + filp_close(fp, NULL); + return -1; + } + + retLen = fp->f_op->read(fp, buf, len, offset); + + set_fs(old_fs); + filp_close(fp, NULL); + + return retLen; +} + +static ssize_t file_write(char *filename, char *buf, size_t len, loff_t *offset) +{ + struct file *fp; + mm_segment_t old_fs; + ssize_t retLen; + + fp = filp_open(filename, O_WRONLY | O_CREAT, 0644); + if (IS_ERR(fp)) { + BT_WARN_FUNC("Failed to open %s!\n", filename); + return -1; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if ((fp->f_op == NULL) || (fp->f_op->write == NULL)){ + BT_WARN_FUNC("File can not be write!\n"); + set_fs(old_fs); + filp_close(fp, NULL); + return -1; + } + + retLen = fp->f_op->write(fp, buf, len, offset); + + set_fs(old_fs); + filp_close(fp, NULL); + + return retLen; +} + +int load_custom_bt_conf(struct btradio_conf_data *cfg) +{ + /* + This method depends on customer's platform configuration data + store machenism. + Customer may use NVRAM, data file, or other patterns. + Here RECOMMEND and GIVE AN EXAMPLE to push configuration data + under /data/BT.cfg + */ + + struct btradio_conf_data temp; + loff_t pos = 0; + ssize_t retLen; + + retLen = file_read(CUSTOM_BT_CFG_FILE, + (char*)&temp, + sizeof(temp), + &pos); + + if (retLen < 0) + return -1; + + if(retLen < sizeof(temp)){ + BT_ERR_FUNC("File read error len: %d\n", retLen); + return -1; + } + else{ + memcpy(cfg, &temp, retLen); + return 0; + } +} + +int load_internal_bt_conf(struct btradio_conf_data *cfg) +{ + struct btradio_conf_data temp; + loff_t pos = 0; + ssize_t retLen; + ssize_t written; + + retLen = file_read(INTERNAL_BT_CFG_FILE, + (char*)&temp, + sizeof(temp), + &pos); + + if (retLen < 0){ + BT_INFO_FUNC("No internal BT config, generate from default value\n"); + memcpy(&temp, &sDefaultCfg, sizeof(struct btradio_conf_data)); + + // Generate internal BT config file + pos = 0; + written = file_write(INTERNAL_BT_CFG_FILE, + (char*)&temp, + sizeof(temp), + &pos); + if (written < 0){ + BT_ERR_FUNC("Try to create internal BT config, error\n"); + return -1; + } + else if(written < sizeof(temp)){ + BT_ERR_FUNC("File write error len: %d\n", written); + } + else{ + BT_INFO_FUNC("Internal BT config generated\n"); + } + + memcpy(cfg, &temp, sizeof(temp)); + return 0; + } + else if(retLen < sizeof(temp)){ + BT_ERR_FUNC("File read error len: %d\n", retLen); + } + + memcpy(cfg, &temp, retLen); + return 0; +} + + +static inline void hci_stp_tx_skb_comp (struct hci_stp *hu, struct sk_buff *skb) +{ + struct hci_dev *hdev; + int pkt_type; + + + hdev = hu->hdev; + hdev->stat.byte_tx += skb->len; + + pkt_type = bt_cb(skb)->pkt_type; + /* Update HCI stat counters */ + switch (pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + hdev->stat.cmd_tx++; + break; + } +} + +#if (HCI_STP_TX == HCI_STP_TX_TASKLET) +void hci_stp_tx_init (struct hci_stp *hu) +{ + tasklet_init(&hci_tx_tasklet, hci_stp_tx_tasklet_func, (unsigned long)hu); + + #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) + rwlock_init(&hci_stp_txqlock); + #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) + spin_lock_init(&hci_stp_txqlock); + #endif +} + +void hci_stp_tx_deinit (struct hci_stp *hu) +{ + tasklet_kill(&hci_tx_tasklet); + + return; +} + +void hci_stp_txq_lock (unsigned int ctx) +{ + if (ctx == HCI_STP_TXQ_IN_BLZ) { + /* lock txq in BlueZ tx tasklet context */ + #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) + write_lock_bh(&hci_stp_txqlock); + #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) + spin_lock_bh(&hci_stp_txqlock); + #else + #error "HCI_STP_TX_TASKLET_LOCK" + #endif + } + else { + /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */ + #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) + write_lock_bh(&hci_stp_txqlock); + #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) + spin_lock_bh(&hci_stp_txqlock); + #else + #error "HCI_STP_TX_TASKLET_LOCK" + #endif + } +} + +void hci_stp_txq_unlock (unsigned int ctx) +{ + if (ctx == HCI_STP_TXQ_IN_BLZ) { + /* lock txq in BlueZ tx tasklet context with hci_stp_tx */ + #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) + write_unlock_bh(&hci_stp_txqlock); + #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) + spin_unlock_bh(&hci_stp_txqlock); + #else + #error "HCI_STP_TX_TASKLET_LOCK" + #endif + } + else { + /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */ + #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK) + write_unlock_bh(&hci_stp_txqlock); + #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK) + spin_unlock_bh(&hci_stp_txqlock); + #else + #error "HCI_STP_TX_TASKLET_LOCK" + #endif + } +} + +void hci_stp_tx_kick (void) +{ + tasklet_schedule(&hci_tx_tasklet); +} + +static void hci_stp_tx_tasklet_func(unsigned long data) { + + struct hci_stp *hu = (struct hci_stp *)data; + + /* sanity check to see if status is still correct? */ + if (unlikely(hdev == NULL)) { + BT_ERR_FUNC("Null hdev!\n"); + BUG_ON(hdev == NULL); + return; + } + + if (unlikely(hu != hdev->driver_data)) { + BT_ERR_FUNC("hu(0x%p) != hdev->driver_data(0x%p)\n", + hu, hdev->driver_data); + BUG_ON(hu != hdev->driver_data); + return; + } + + //read_lock(&hci_stp_txq_lock); + hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP); + + hci_stp_tx_wakeup(hu); + + //read_unlock(&hci_stp_txq_lock); + hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP); +} + +/* George: HCI_STP_SENDING and HCI_STP_TX_WAKEUP flags in this function seem +* to be redundant. +*/ +static int hci_stp_tx_wakeup(struct hci_stp *hu) +{ +// struct hci_dev *hdev = hu->hdev; + struct sk_buff *skb; + int j = 0; + + BT_TRC_FUNC(); + + if (test_and_set_bit(HCI_STP_SENDING, &hu->tx_state)) { + set_bit(HCI_STP_TX_WAKEUP, &hu->tx_state); + printk("[BT] enqueue and return\n"); + return 0; + } + + BT_DBG_FUNC("hci_stp_tx_wakeup %d\n", __LINE__); + +restart: + clear_bit(HCI_STP_TX_WAKEUP, &hu->tx_state); + + while ((skb = skb_dequeue(&hu->txq))) { + int len; + BT_DBG_FUNC("dqueue times = %d\n", ++j); + + /* hci reset cmd check */ +#if HCI_STP_SAFE_RESET + if (unlikely(skb->len == ARRAY_SIZE(bt_reset))) { + if (unlikely(!memcmp(bt_reset, skb->data, ARRAY_SIZE(bt_reset)))) { + atomic_inc(&hu->reset_count); + BT_DBG_FUNC("hci reset cmd,f(%d),c(%d)\n", + BT_GET_HDEV_RST_FG(hdev), + atomic_read(&hu->reset_count)); + } + } +#endif + + if ((len = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX)) == 0 ) { + /* can not send */ + BT_ERR_FUNC("mtk_wcn_stp_send_data can not send\n"); + BT_ERR_FUNC("Error %s %d\n", __FUNCTION__, __LINE__); + + skb_queue_head(&hu->txq, skb);//Put back to queue head + goto END; + } + + //hdev->stat.byte_tx += len; // moved into hci_stp_tx_skb_comp() + //hci_stp_tx_skb_comp(hu, bt_cb(skb)->pkt_type); + hci_stp_tx_skb_comp(hu, skb); + kfree_skb(skb); + } + +END: + if (test_bit(HCI_STP_TX_WAKEUP, &hu->tx_state)) + goto restart; + + clear_bit(HCI_STP_SENDING, &hu->tx_state); + + return 0; +} + + +#elif (HCI_STP_TX == HCI_STP_TX_THRD) + +void hci_stp_tx_init (struct hci_stp *hu) +{ + spin_lock_init(&hci_stp_txqlock); + init_waitqueue_head(&hci_stp_tx_thrd_wq); + + hci_stp_tx_thrd = kthread_create(hci_stp_tx_thrd_func, (void *)hu, "hci_stpd"); + if (NULL == hci_stp_tx_thrd) { + BT_ERR_FUNC("kthread_create hci_stpd fail!\n"); + } + wake_up_process(hci_stp_tx_thrd); + + return; +} + +void hci_stp_tx_deinit (struct hci_stp *hu) +{ + kthread_stop(hci_stp_tx_thrd); + hci_stp_tx_thrd = NULL; + + return; +} + +void hci_stp_txq_lock (unsigned int ctx) +{ + if (ctx == HCI_STP_TXQ_IN_BLZ) { + /* lock txq in BlueZ tx tasklet context */ + spin_lock(&hci_stp_txqlock); + } + else { + /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */ + spin_lock_bh(&hci_stp_txqlock); + } +} + +void hci_stp_txq_unlock (unsigned int ctx) +{ + if (ctx == HCI_STP_TXQ_IN_BLZ) { + spin_unlock(&hci_stp_txqlock); + } + else { + /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */ + spin_unlock_bh(&hci_stp_txqlock); + } +} + +static int +hci_stp_tx_thrd_func (void *pdata) +{ + struct hci_stp *hu; + struct hci_dev *hdev; + struct sk_buff *skb; + int len; + + hu = (struct hci_stp *)pdata; + hdev = hu->hdev; + + /* sanity check to see if status is still correct? */ + if (unlikely(hdev == NULL)) { + BT_ERR_FUNC("Null hdev!\n"); + BUG_ON(hdev == NULL); + return -1; + } + + if (unlikely(hu != hdev->driver_data)) { + BT_ERR_FUNC("hu(0x%p) != hdev->driver_data(0x%p)\n", + hu, hdev->driver_data); + BUG_ON(hu != hdev->driver_data); + return -1; + } + + for (;;) { + smp_rmb(); /* sync shared data */ + + wait_event_interruptible(hci_stp_tx_thrd_wq, + (!skb_queue_empty(&hu->txq) || kthread_should_stop())); + + if (unlikely(kthread_should_stop())) { + BT_DBG_FUNC("hci_stpd thread should stop now... \n"); + break; + } + + hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP); + while ((skb = skb_dequeue(&hu->txq))) { + /* protect txq only */ + hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP); + + /* hci reset cmd check */ + #if HCI_STP_SAFE_RESET + if (unlikely(skb->len == ARRAY_SIZE(bt_reset))) { + if (unlikely(!memcmp(bt_reset, skb->data, ARRAY_SIZE(bt_reset)))) { + atomic_inc(&hu->reset_count); + BT_DBG_FUNC("hci reset cmd,f(%d),c(%d)\n", + BT_GET_HDEV_RST_FG(hdev), + atomic_read(&hu->reset_count)); + } + } + #endif + + len = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX); + if (unlikely(len != skb->len)) { + /* can not send */ + BT_ERR_FUNC("mtk_wcn_stp_send_data fail, enqueue again!(%d, %d)\n", + len, skb->len); + + hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP); + skb_queue_head(&hu->txq, skb);//Put back to queue head + /* do hci_stp_txq_unlock outside while loop */ + break; + } + //hdev->stat.byte_tx += len; // moved into hci_stp_tx_skb_comp() + hci_stp_tx_skb_comp(hu, skb); + kfree_skb(skb); + + hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP); + } + hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP); + + /* back to wait */ + } + + BT_INFO_FUNC("tx thread stop!\n"); + return 0; +} + +void hci_stp_tx_kick (void) +{ + smp_wmb(); + wake_up_interruptible(&hci_stp_tx_thrd_wq); +} + +#else +#error "Not implemented HCI_STP_TX" +#endif + + +void hci_stp_dev_init_rx_cb (const UINT8 *data, INT32 count) +{ + struct hci_stp *hu; + unsigned int idx; + + if (unlikely(!hdev)) { + BT_ERR_FUNC("null hdev!\n"); + return; + } + if (unlikely(!hdev->driver_data)) { + BT_ERR_FUNC("null hdev->driver_data!\n"); + return; + } + + /* get hci_stp from global variable */ + hu = (struct hci_stp *)hdev->driver_data; + idx = hu->init_cmd_idx; + + if (unlikely(count != init_table[idx].evtSz)){ + hu->init_evt_rx_flag = -1; /* size mismatch */ + } + else if (unlikely(memcmp(data, init_table[idx].hci_evt, 7))){ + hu->init_evt_rx_flag = -2; /* content mismatch */ + } + else{ + hu->init_evt_rx_flag = 1; /* ok */ + BT_DBG_FUNC("EVT(%d) len(%d) ok\n", idx, count); + if (idx == 0) { + /* store the returned eFUSE address */ + memcpy(&bt_get_bd_addr_evt[7], &data[7], 6); + } + } + + if (unlikely(1 != hu->init_evt_rx_flag)) { + int i; + BT_WARN_FUNC("EVT(%d) len(%d) buf:[", idx, count); + for (i = 0; i < count; ++i) { + printk("0x%02x ", data[i]); + } + printk("]\n"); + BT_WARN_FUNC("EVT(%d) exp(%d) buf:[", idx, init_table[idx].evtSz); + for (i = 0; i < count; ++i) { + printk("0x%02x ", init_table[idx].hci_evt[i]); + } + printk("]\n"); + + } + + smp_wmb(); /* sync shared data */ + + spin_lock(&hu->init_lock); + if (likely(hu->p_init_evt_wq)) { + wake_up(hu->p_init_evt_wq); /* wake up dev_init_work */ + } + else { + int i; + BT_WARN_FUNC("late EVT(%d) len(%d) buf:[", idx, count); + for (i = 0; i < count; ++i) { + printk("0x%02x ", data[i]); + } + printk("]\n"); + BT_WARN_FUNC("Please check if uart rx data is returned or processed in time for BT init!\n"); + BT_WARN_FUNC("Possibly caused by a very busy system, or stp_uart rx priority too low...\n"); + BT_WARN_FUNC("Check which one is the real case and try to raise stp_uart rx priority.\n"); + } + spin_unlock(&hu->init_lock); +} + +static void hci_stp_dev_init_work (struct work_struct *work) +{ + struct hci_stp *phu; + unsigned int idx; + long ret, to; + + struct btradio_conf_data cfg = { + {0x00, 0x00, 0x46, 0x66, 0x20, 0x01}, + {0x60, 0x00}, + {0x23, 0x10, 0x00, 0x00}, + {0x06, 0x80, 0x00, 0x06, 0x03, 0x06}, + {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04}, + {0x80, 0x00}, + {0xFF, 0xFF, 0xFF}}; + + /* get client's information */ + phu = container_of(work, struct hci_stp, init_work); + + if (load_custom_bt_conf(&cfg) < 0){ + BT_INFO_FUNC("No custom BT config\n"); + + if (load_internal_bt_conf(&cfg) < 0){ + BT_ERR_FUNC("Load internal BT config failed!\n"); + } + else{ + BT_INFO_FUNC("Load internal BT config success\n"); + + if (0 == memcmp(cfg.addr, sDefaultCfg.addr, 6)){ + /* BD address default value, want to retrieve module eFUSE */ + fgetEFUSE = true; + /* retrieve eFUSE address in init command loop */ + } + } + } + else{ + BT_INFO_FUNC("Load custom BT config success\n"); + } + + BT_DBG_FUNC("Read BT config data:\n"); + BT_DBG_FUNC("[BD address %02x-%02x-%02x-%02x-%02x-%02x]\n", + cfg.addr[0], cfg.addr[1], cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]); + BT_DBG_FUNC("[voice %02x %02x][codec %02x %02x %02x %02x]\n", + cfg.voice[0], cfg.voice[1], cfg.codec[0], cfg.codec[1], cfg.codec[2], cfg.codec[3]); + BT_DBG_FUNC("[radio %02x %02x %02x %02x %02x %02x]\n", + cfg.radio[0], cfg.radio[1], cfg.radio[2], cfg.radio[3], cfg.radio[4], cfg.radio[5]); + BT_DBG_FUNC("[sleep %02x %02x %02x %02x %02x %02x %02x]\n", + cfg.sleep[0], cfg.sleep[1], cfg.sleep[2], cfg.sleep[3], cfg.sleep[4], cfg.sleep[5], cfg.sleep[6]); + BT_DBG_FUNC("[feature %02x %02x]\n", + cfg.feature[0], cfg.feature[1]); + BT_DBG_FUNC("[tx power offset %02x %02x %02x]\n", + cfg.tx_pwr_offset[0], cfg.tx_pwr_offset[1], cfg.tx_pwr_offset[2]); + + bt_set_bd_addr[4] = cfg.addr[5]; + bt_set_bd_addr[5] = cfg.addr[4]; + bt_set_bd_addr[6] = cfg.addr[3]; + bt_set_bd_addr[7] = cfg.addr[2]; + bt_set_bd_addr[8] = cfg.addr[1]; + bt_set_bd_addr[9] = cfg.addr[0]; + + memcpy(&bt_set_voice[4], cfg.voice, 2); + memcpy(&bt_set_codec[4], cfg.codec, 4); + memcpy(&bt_set_radio[4], cfg.radio, 6); + memcpy(&bt_set_tx_pwr_offset[4], cfg.tx_pwr_offset, 3); + memcpy(&bt_set_sleep[4], cfg.sleep, 7); + memcpy(&bt_set_feature[4], cfg.feature, 2); + + /* + * INIT command loop starts + */ + if (fgetEFUSE == true) + idx = 0; + else // skip bt_get_bd_addr + idx = 1; + + for (; idx < ARRAY_SIZE(init_table); ++idx) { + phu->init_cmd_idx = idx; + phu->init_evt_rx_flag = 0; + to = (init_table[idx].hci_cmd == bt_reset) ? BT_CMD_DELAY_MS_RESET : BT_CMD_DELAY_MS_COMM; + /* safe waiting time in case running on a busy system */ + to = msecs_to_jiffies(to * BT_CMD_DELAY_SAFE_GUARD); + + BT_DBG_FUNC("CMD(%d) (%s) t/o(%ld))\n", idx, init_table[idx].str, to); + smp_wmb(); /* sync shared data */ + + /* Send hci command */ + mtk_wcn_stp_send_data(init_table[idx].hci_cmd, init_table[idx].cmdSz, BT_TASK_INDX); + /* Wait rx hci event */ + /* no need to lock init_lock here for wq, for that it will be freed + * only after we call complete(phu->p_init_comp); in this function. + */ + ret = wait_event_timeout((*phu->p_init_evt_wq), phu->init_evt_rx_flag != 0, to); + + /* Check result */ + if (likely(1 == phu->init_evt_rx_flag)) { + if (idx == 0) + { // bt_get_bd_addr event handler + unsigned long randNum; + loff_t pos = 0; + ssize_t written; + + BT_DBG_FUNC("Retrieve eFUSE address %02x-%02x-%02x-%02x-%02x-%02x\n", + bt_get_bd_addr_evt[12], bt_get_bd_addr_evt[11], bt_get_bd_addr_evt[10], bt_get_bd_addr_evt[9], bt_get_bd_addr_evt[8], bt_get_bd_addr_evt[7]); + + cfg.addr[0] = bt_get_bd_addr_evt[12]; + cfg.addr[1] = bt_get_bd_addr_evt[11]; + cfg.addr[2] = bt_get_bd_addr_evt[10]; + cfg.addr[3] = bt_get_bd_addr_evt[9]; + cfg.addr[4] = bt_get_bd_addr_evt[8]; + cfg.addr[5] = bt_get_bd_addr_evt[7]; + + if (0 == memcmp(cfg.addr, sDefaultCfg.addr, 6)){ + #if BD_ADDR_AUTOGEN + /* eFUSE address default value, enable auto-gen */ + BT_DBG_FUNC("eFUSE address default value, enable auto-gen!\n"); + get_random_bytes(&randNum, sizeof(unsigned long)); + BT_DBG_FUNC("Get random number: %lu\n", randNum); + + bt_get_bd_addr_evt[12] = (((randNum>>24 | randNum>>16) & (0xFE)) | (0x02)); + bt_get_bd_addr_evt[11] = ((randNum>>8) & 0xFF); + bt_get_bd_addr_evt[7] = (randNum & 0xFF); + + cfg.addr[0] = bt_get_bd_addr_evt[12]; + cfg.addr[1] = bt_get_bd_addr_evt[11]; + cfg.addr[5] = bt_get_bd_addr_evt[7]; + #endif + } + else { + /* eFUSE address has valid value */ + } + + memcpy(&bt_set_bd_addr[4], &bt_get_bd_addr_evt[7], 6); + + /* Update BD address in internal BT config file */ + pos = 0; + written = file_write(INTERNAL_BT_CFG_FILE, + (char*)&cfg, + 6, + &pos); + + /* Clear flag */ + fgetEFUSE = false; + } + /* Process next cmd */ + continue; + } + else { + BT_ERR_FUNC("EVT(%d) ret(%u) rx_flag(%d)<=\n", + idx, jiffies_to_msecs(ret), phu->init_evt_rx_flag); + /* Stop processing and skip next cmd */ + break; + } + } + + if (phu->p_init_comp) { + complete(phu->p_init_comp); + } +} + +static int hci_stp_dev_init (struct hci_stp *phu) +{ + DECLARE_COMPLETION_ONSTACK(hci_stp_dev_init_comp); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(hci_stp_dev_init_wq); + + spin_lock(&phu->init_lock); + phu->p_init_comp = &hci_stp_dev_init_comp; + phu->p_init_evt_wq = &hci_stp_dev_init_wq; + spin_unlock(&phu->init_lock); + + /* unregister rx event callback */ + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + /* register direct rx callback for init only */ + mtk_wcn_stp_register_if_rx(hci_stp_dev_init_rx_cb); + /* use bluez mode */ + mtk_wcn_stp_set_bluez(1); + + /* Schedule to call hci_stp_dev_init_work(). init_work is initialized in + * hci_stp_init(). + */ + schedule_work(&phu->init_work); + + wait_for_completion(&hci_stp_dev_init_comp); + + spin_lock(&phu->init_lock); + /* clear references to stack variables */ + phu->p_init_comp = NULL; + phu->p_init_evt_wq = NULL; + spin_unlock(&phu->init_lock); + + /* check result */ + /* flag: (to be replaced by a constant value) + 1 rx event correctly, + 0 no response in time, + -1 unequal rx event length, + -2 unequal rx event content. + */ + if (likely(1 == phu->init_evt_rx_flag)) { + return 0; + } + else { + /* return non-zero value for error */ + return (phu->init_evt_rx_flag + 256); + } +} + +/* Invoked when there is ONE received BT packet */ +void stp_tx_event_cb(void) +{ +#if 0 + struct hci_stp *hu; + if (unlikely(hdev == NULL)) { + BT_ERR_FUNC("Null hdev!\n"); + BUG_ON(hdev == NULL); + return; + } + hu = (struct hci_stp *) hdev->driver_data; +#endif + /* George: [FixMe] can we call hci_stp_tx_wakeup() directly in STP-CORE's + * context? It seems to be dangerous! Replace it with suitable one according + * to HCI_STP_TX compile flag. + */ + hci_stp_tx_kick(); /* George: adapt different tx_kick function */ +} + +/* + Direct delivery of bluez not changed hands through the stp buffer +*/ +void stp_rx_event_cb_directly(const UINT8 *data, INT32 count) +{ + register const UINT8 *ptr; + struct hci_event_hdr *eh; + struct hci_acl_hdr *ah; + struct hci_sco_hdr *sh; + register int len, type, dlen; + int while_count; /* = 0; Is while_count redundant? */ + //static unsigned long rx_count; /* Is it ok w/o an initial value??? */ + static unsigned int rx_count = 0; + //static unsigned long rx_state; /* Is it ok w/o an initial value??? */ + static unsigned int rx_state = H4_W4_PACKET_TYPE; + struct sk_buff *rx_skb = NULL; /* Is it ok to use non-static skb??? */ + register int room; +#if HCI_STP_SAFE_RESET + struct hci_stp *hu; +#endif + + BT_LOUD_FUNC("count(%d)rx_state(%d)rx_count(%d)\n", + count, rx_state, rx_count); + + if (data == NULL) { + BT_ERR_FUNC("Data is Null\n"); + return; + } + + if (count > 5000) { + BT_WARN_FUNC("abnormal count(%d)\n", count); + } + + ptr = data; + /*Add statistic*/ + hdev->stat.byte_rx += count; + +#if HCI_STP_SAFE_RESET + hu = (struct hci_stp *)hdev->driver_data; + /* is waiting hci reset event? */ + if (unlikely(atomic_read(&hu->reset_count))) { + if (count == ARRAY_SIZE(bt_reset_evt)) { + if (!memcmp(bt_reset_evt, data, ARRAY_SIZE(bt_reset_evt))) { + BT_DBG_FUNC("hci reset evt,f(%d),c(%d)\n", + BT_GET_HDEV_RST_FG(hdev), + atomic_read(&hu->reset_count)); + + atomic_dec(&hu->reset_count); + wake_up(&hu->reset_wq); + } + } + } +#endif + + while_count = 0; + while (count > 0) { /* while (count) */ + /* Is while_count redundant? */ + //while_count++; + if (++while_count > 5000) { + BT_WARN_FUNC("abnormal while_count(%d)\n", while_count); + } + + if (rx_count) { + len = min_t(unsigned int, rx_count, count); + memcpy(skb_put(rx_skb, len), ptr, len); + rx_count -= len; + count -= len; + ptr += len; + + if (rx_count) + continue; + /* rx_count==0, ready to indicate to hci_core */ + + switch (rx_state) { + case H4_W4_DATA: + BT_LOUD_FUNC("Complete data\n"); + hci_recv_frame(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + continue; + + case H4_W4_EVENT_HDR: + eh = hci_event_hdr(rx_skb); + //BT_DBG_FUNC("Event header:evt(0x%2.2x)plen(%d)\n", eh->evt, eh->plen); + room = skb_tailroom(rx_skb); + //BT_DBG_FUNC("len(%d)room(%d)\n", eh->plen, room); + BT_LOUD_FUNC("Event header:evt(0x%2.2x)plen(%d)room(%d)\n", + eh->evt, eh->plen, room); + + if (!eh->plen) { + hci_recv_frame(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; /* redundant? here rx_count is 0 already */ + } + else if (eh->plen > room) { + //BT_ERR("Data length is too large\n"); + BT_ERR_FUNC("too large data length:eh->plen(%d)>room(%d)\n", + eh->plen, room); + kfree_skb(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; /* redundant? here rx_count is 0 already */ + } + else { + rx_state = H4_W4_DATA; + rx_count = eh->plen; + } + continue; + + case H4_W4_ACL_HDR: + ah = hci_acl_hdr(rx_skb); + dlen = __le16_to_cpu(ah->dlen); + + room = skb_tailroom(rx_skb); + BT_LOUD_FUNC("ACL header:dlen(%d)room(%d)\n", dlen, room); + if (!dlen) { + hci_recv_frame(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; + } + else if (dlen > room) { + //BT_ERR_FUNC("Data length is too large\n"); + BT_ERR_FUNC("too large data length:dlen(%d)>room(%d)\n", + dlen, room); + kfree_skb(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; + } + else { + rx_state = H4_W4_DATA; + rx_count = dlen; + } + continue; + + case H4_W4_SCO_HDR: + sh = hci_sco_hdr(rx_skb); + room = skb_tailroom(rx_skb); + BT_LOUD_FUNC("SCO header:dlen(%d)room(%d)\n", sh->dlen, room); + + if (!sh->dlen) { + hci_recv_frame(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; + } + else if (sh->dlen > room) { + BT_ERR_FUNC("Data length is too large\n"); + BT_ERR_FUNC("too large data length:sh->dlen(%d)>room(%d)\n", + sh->dlen , room); + kfree_skb(rx_skb); + rx_state = H4_W4_PACKET_TYPE; + rx_skb = NULL; + rx_count = 0; + } + else { + rx_state = H4_W4_DATA; + rx_count = sh->dlen; + } + continue; + } + } + + /* H4_W4_PACKET_TYPE */ + switch (*ptr) { + case HCI_EVENT_PKT: + BT_LOUD_FUNC("Event packet\n"); + rx_state = H4_W4_EVENT_HDR; + rx_count = HCI_EVENT_HDR_SIZE; + type = HCI_EVENT_PKT; + break; + + case HCI_ACLDATA_PKT: + BT_LOUD_FUNC("ACL packet\n"); + rx_state = H4_W4_ACL_HDR; + rx_count = HCI_ACL_HDR_SIZE; + type = HCI_ACLDATA_PKT; + break; + + case HCI_SCODATA_PKT: + BT_LOUD_FUNC("SCO packet\n"); + rx_state = H4_W4_SCO_HDR; + rx_count = HCI_SCO_HDR_SIZE; + type = HCI_SCODATA_PKT; + break; + + default: + BT_ERR_FUNC("Unknown HCI packet type %2.2x\n", (__u8)*ptr); + ++(hdev->stat.err_rx); + ++ptr; + --count; + continue; + }; + + ++ptr; + --count; + + /* Allocate packet */ + rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); + if (!rx_skb) { + BT_ERR_FUNC("bt_skb_alloc(%d, GFP_ATOMIC) fail!\n", HCI_MAX_FRAME_SIZE); + rx_state = H4_W4_PACKET_TYPE; + rx_count = 0; + return; + } + + rx_skb->dev = (void *) hdev; + bt_cb(rx_skb)->pkt_type = type; + } + + return; +} + +/* ------- Interface to HCI layer ------ */ +/* Initialize device */ +static int hci_stp_open(struct hci_dev *hdev) +{ + struct hci_stp *hu; + int ret; + + if (unlikely(!hdev)) { + BT_ERR_FUNC("null hdev\n"); + return -ENODEV; + } + + if (unlikely(!hdev->driver_data)) { + BT_ERR_FUNC("null hdev\n"); + return -ENODEV; + } + + hu = (struct hci_stp *)hdev->driver_data; + BT_INFO_FUNC("%s(0x%p)\n", hdev->name, hdev); + + /* clear txq and free all skb in it */ + hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ); + skb_queue_purge(&hu->txq); + hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ); + + /* turn on BT */ + if (unlikely(MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT))) { + BT_WARN_FUNC("WMT turn on BT fail!\n"); + return -ENODEV; + } + + BT_INFO_FUNC("WMT turn on BT OK!\n"); + + if (likely(mtk_wcn_stp_is_ready())) { + BT_DBG_FUNC("STP is ready!\n"); + + ret = hci_stp_dev_init(hu); + /* error handling: turn off BT */ + if (unlikely(ret)) { + BT_WARN_FUNC("hci_stp_dev_init fail(%d)!\n", ret); + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) { + BT_WARN_FUNC("WMT turn off BT fail!\n"); + } + else { + BT_INFO_FUNC("WMT turn off BT ok!\n"); + } + return -ENODEV; + } + + BT_INFO_FUNC("hci_stp_dev_init ok\n"); + + set_bit(HCI_RUNNING, &hdev->flags); + + /* registered tx/rx path */ + mtk_wcn_stp_register_if_rx(stp_rx_event_cb_directly); + + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, stp_tx_event_cb); + + /* use bluez */ + mtk_wcn_stp_set_bluez(1); + + return 0; + } + else { + BT_WARN_FUNC("STP is not ready!\n"); + return -ENODEV; + } +} + +/* Reset device */ +static int hci_stp_flush(struct hci_dev *hdev) +{ + struct hci_stp *hu; + + BT_DBG_FUNC("start\n"); + if (!hdev || !hdev->driver_data) { + BT_WARN_FUNC("invalid hdev(0x%p) or drv data(0x%p)\n", + hdev, (hdev) ? hdev->driver_data : hdev); + return -EFAULT; + } + + hu = (struct hci_stp *)hdev->driver_data; + + /* clear txq and free all skb in it */ + hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ); + skb_queue_purge(&hu->txq); + hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ); + + BT_INFO_FUNC("done\n"); + return 0; +} + +/* Close device */ +static int hci_stp_close(struct hci_dev *hdev) +{ +#if HCI_STP_SAFE_RESET + struct hci_stp *hu; + long ret; +#endif + + BT_INFO_FUNC("hdev(0x%p)\n", hdev); + + if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) { + return 0; + } + + hci_stp_flush(hdev); + hdev->flush = NULL; + +#if HCI_STP_SAFE_RESET + hu = (struct hci_stp *)hdev->driver_data; + if (hu) { + /* double waiting time in case of busy system */ + ret = wait_event_timeout((hu->reset_wq), + (atomic_read(&hu->reset_count) == 0), + msecs_to_jiffies(BT_CMD_DELAY_MS_RESET*2)); + if ( (!ret) || (atomic_read(&hu->reset_count) != 0) ) { + BT_WARN_FUNC("wait on-going reset finish fail,f(%d),c(%d),ret(%u)\n", + BT_GET_HDEV_RST_FG(hdev), + atomic_read(&hu->reset_count), + jiffies_to_msecs(ret)); + } + else { + BT_DBG_FUNC("check reset log,f(%d),c(%d),ret(%u)\n", + BT_GET_HDEV_RST_FG(hdev), + atomic_read(&hu->reset_count), + jiffies_to_msecs(ret)); + } + } +#endif + + /* clear txq and free all skb in it */ + hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ); + skb_queue_purge(&hu->txq); + hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ); + + /* unregistered tx/rx path */ + mtk_wcn_stp_register_if_rx(NULL); + + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL); + + /* not use bluez */ + mtk_wcn_stp_set_bluez(0); + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) { + BT_WARN_FUNC("WMT turn off BT fail!\n"); + } + else { + BT_INFO_FUNC("WMT turn off BT OK!\n"); + } + + return 0; +} + +/* Send frames from HCI layer */ +static int hci_stp_send_frame(struct sk_buff *skb) +{ + struct hci_dev* hdev = (struct hci_dev *) skb->dev; + struct hci_stp *hu; + + if (!hdev) { + BT_ERR_FUNC("Null hdev in skb\n"); + return -ENODEV; + } + + if (!test_bit(HCI_RUNNING, &hdev->flags)) { + BT_ERR_FUNC("no HCI_RUNNING in hdev->flags(0x%lx)\n", hdev->flags); + return -EBUSY; + } + + hu = (struct hci_stp *) hdev->driver_data; + + BT_LOUD_FUNC("%s: type(%d) len(%d)\n", + hdev->name, bt_cb(skb)->pkt_type, skb->len); + +#if 0 /* just timestamp?? */ + if (gDbgLevel >= BT_LOG_DBG) + { + struct timeval now; + do_gettimeofday(&now); + printk("%s: sec = %ld, --> usec --> %ld\n", + __FUNCTION__, now.tv_sec, now.tv_usec); + } +#endif + + /* Prepend skb with frame type. Is it safe to do skb_push? */ + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); + + /* George: is no lock ok?? Add hci_stp_txq_lock and unlock! */ + hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ); + /*Queue a buffer at the end of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + */ + skb_queue_tail(&hu->txq, skb); + hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ); + + /* George: adapt different tx_kick function */ + hci_stp_tx_kick(); + + return 0; +} + +static void hci_stp_destruct(struct hci_dev *hdev) +{ + BT_TRC_FUNC(); + + if (!hdev) { + return; + } + + BT_DBG_FUNC("%s\n", hdev->name); + hci_stp_tx_deinit((struct hci_stp *)hdev->driver_data); + kfree(hdev->driver_data); +} + +static int __init hci_stp_init(void) +{ + struct hci_stp *hu = NULL; + + if (!(hu = kzalloc(sizeof(struct hci_stp), GFP_ATOMIC))) { + BT_ERR_FUNC("Can't allocate control structure\n"); + return -ENOMEM; + } + + BT_DBG_FUNC("hu 0x%08x\n", (int)hu); + + /* + used to stored pending skb + */ + skb_queue_head_init(&hu->txq); + + /* + Initialize and register HCI device + */ + hdev = hci_alloc_dev(); + if (!hdev) { + if (hu){ + kfree(hu); + hu = NULL; + } + + BT_ERR_FUNC("Can't allocate HCI device\n"); + return -ENOMEM; + } + + hu->hdev = hdev; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) + hdev->type = HCI_UART; +#else + hdev->bus = HCI_UART; + hdev->dev_type = HCI_BREDR; +#endif + hdev->driver_data = hu; + + BT_DBG_FUNC("hdev->driver_data 0x%08x\n", (int)hdev->driver_data); + hdev->open = hci_stp_open; + hdev->close = hci_stp_close; + hdev->flush = hci_stp_flush; + hdev->send = hci_stp_send_frame; + hdev->destruct = hci_stp_destruct; + + hdev->owner = THIS_MODULE; + + BT_DBG_FUNC("HCI_QUIRK_NO_RESET\n"); + + set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); + + if (hci_register_dev(hdev) < 0) { + BT_ERR_FUNC("Can't register HCI device\n"); + kfree(hu); + hu = NULL; + hci_free_dev(hdev); + hdev = NULL; + return -ENODEV; + } + +#if HCI_STP_SAFE_RESET + atomic_set(&hu->reset_count, 0); + init_waitqueue_head(&hu->reset_wq); +#endif + + /* George: adapt different tx_init function */ + hci_stp_tx_init(hu); + + /* init_work in heap */ + INIT_WORK(&hu->init_work, hci_stp_dev_init_work); + spin_lock_init(&hu->init_lock); + + mtk_wcn_stp_register_if_rx(NULL); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL); + + BT_INFO_FUNC("HCI STP driver ver %s, hdev(0x%p), init done\n", VERSION, hdev); + + return 0; +} + +static void __exit hci_stp_exit(void) +{ + struct hci_stp *hu = (struct hci_stp *)hdev->driver_data; + + BT_TRC_FUNC(); + + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL); + + hci_unregister_dev(hdev); + + /* George: adapt different tx_deinit function */ + //tasklet_kill(&hci_tx_tasklet); + + skb_queue_purge(&hu->txq); + + /* hci_stp_destruct does this */ + /*kfree(hdev->driver_data);*/ + hci_free_dev(hdev); + + hdev = NULL; +} + +module_init(hci_stp_init); +module_exit(hci_stp_exit); + +module_param(reset, bool, 0644); +MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); + +MODULE_AUTHOR("Mediatek Inc."); +MODULE_DESCRIPTION("Bluetooth HCI STP driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/mtk_wcn_combo/drv_fm/Makefile b/drivers/mtk_wcn_combo/drv_fm/Makefile new file mode 100755 index 000000000000..e9fec34a1bf1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/Makefile @@ -0,0 +1,82 @@ +# Makefile generated by Mediatek +# fm support + +#6628 FM driver +ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6628), y) +$(warning MT6628_FM) +ccflags-y += -I$(src)/inc \ + -I$(src)/mt6628/inc \ + -I$(src)/../common/include \ + -I$(src)/../common/linux/include \ + -I$(src)/cust/mt6628 \ + -I$(src)/private/inc \ + -DMT6628_FM + +obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o + mtk_fm_drv-objs += core/fm_module.o \ + core/fm_main.o \ + core/fm_config.o \ + core/fm_rds_parser.o \ + core/fm_patch.o \ + core/fm_utils.o \ + core/fm_link.o \ + core/fm_eint.o \ + mt6628/pub/mt6628_fm_lib.o \ + mt6628/pub/mt6628_fm_rds.o \ + mt6628/pub/mt6628_fm_cmd.o \ + mt6628/pub/mt6628_fm_config.o +$(warning $(mtk_fm_drv-objs)) +endif + +# MT6620 FM driver +ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6620), y) +$(warning MT6620_FM) + ccflags-y += -I$(src)/inc \ + -I$(src)/mt6620/inc \ + -I$(src)/../common/include \ + -I$(src)/../common/linux/include \ + -I$(src)/cust/mt6620 \ + -I$(src)/private/inc \ + -DMT6620_FM + + obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o + mtk_fm_drv-objs += core/fm_module.o \ + core/fm_main.o \ + core/fm_config.o \ + core/fm_rds_parser.o \ + core/fm_patch.o \ + core/fm_utils.o \ + core/fm_link.o \ + core/fm_eint.o \ + mt6620/pub/mt6620_fm_lib.o \ + mt6620/pub/mt6620_fm_rds.o \ + mt6620/pub/mt6620_fm_cmd.o \ + mt6620/pub/mt6620_fm_config.o +$(warning $(mtk_fm_drv-objs)) +endif + +# MT6626 FM driver +ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6626), y) +FM_CHIP = mt6626 +FM_CHIP_PATH = $(FM_CHIP)/pub/$(FM_CHIP) +ccflags-y := -I$(src)/inc \ + -I$(src)/$(FM_CHIP)/inc \ + -I$(src)/cust/$(FM_CHIP) \ + -I$(src)/private/inc \ + -DMT6626_FM + +obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o +mtk_fm_drv-objs := core/fm_module.o \ + core/fm_main.o \ + core/fm_config.o \ + core/fm_patch.o \ + core/fm_rds_parser.o \ + core/fm_utils.o \ + core/fm_link.o \ + $(FM_CHIP_PATH)_fm_lib.o \ + $(FM_CHIP_PATH)_fm_rds.o \ + $(FM_CHIP_PATH)_fm_link.o \ + $(FM_CHIP_PATH)_fm_eint.o +endif + + diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_config.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_config.c new file mode 100755 index 000000000000..7529ab287510 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_config.c @@ -0,0 +1,597 @@ +/* fm_config.c + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_patch.h" +#include "fm_config.h" +#if (!defined(MT6628_FM)&&!defined(MT6620_FM)) +#include "fm_cust_cfg.h" +#endif +static fm_cust_cfg fm_config; +static fm_s32 fm_index = 0; + +#if 0 +static fm_s32 to_upper(fm_s8 *str) +{ + fm_s32 i = 0; + + for (i = 0; i < (int)strlen(str); i++) { + if (('a' <= str[i]) && (str[i] <= 'z')) { + str[i] = str[i] - ('a' - 'A'); + } + } + + return 0; +} +#endif + +fm_s32 to_upper_n(fm_s8 *str, fm_s32 len) +{ + fm_s32 i = 0; + + for (i = 0; i < len; i++) { + if (('a' <= str[i]) && (str[i] <= 'z')) { + str[i] = str[i] - ('a' - 'A'); + } + } + + return 0; +} + +fm_s32 check_hex_str(fm_s8 *str, fm_s32 len) +{ + fm_s32 i = 0; + + for (i = 0; i < len; i++) { + if ((('a' <= str[i]) && (str[i] <= 'z')) || (('A' <= str[i]) && (str[i] <= 'Z')) || (('0' <= str[i]) && (str[i] <= '9'))) { + ; + } else { + return -1; + } + } + + return 0; +} + +fm_s32 check_dec_str(fm_s8 *str, fm_s32 len) +{ + fm_s32 i = 0; + + for (i = 0; i < len; i++) { + if (('0' <= str[i]) && (str[i] <= '9')) { + ; + } else { + return -1; + } + } + + return 0; +} + +fm_s32 ascii_to_hex(fm_s8 *in_ascii, fm_u16 *out_hex) +{ + fm_s32 len = (fm_s32)strlen(in_ascii); + int i = 0; + fm_u16 tmp; + + len = (len > 4) ? 4 : len; + + if (check_hex_str(in_ascii, len)) { + return -1; + } + + to_upper_n(in_ascii, len); + *out_hex = 0; + + for (i = 0; i < len; i++) { + if (in_ascii[len-i-1] < 'A') { + tmp = in_ascii[len-i-1]; + *out_hex |= ((tmp - '0') << (4 * i)); + } else { + tmp = in_ascii[len-i-1]; + *out_hex |= ((tmp - 'A' + 10) << (4 * i)); + } + } + + return 0; +} + +fm_s32 ascii_to_dec(fm_s8 *in_ascii, fm_s32 *out_dec) +{ + fm_s32 len = (fm_s32)strlen(in_ascii); + int i = 0; + int flag; + int multi = 1; + + len = (len > 10) ? 10 : len; + + if (in_ascii[0] == '-') { + flag = -1; + in_ascii += 1; + len -= 1; + } else { + flag = 1; + } + + if (check_dec_str(in_ascii, len)) { + return -1; + } + + *out_dec = 0; + multi = 1; + + for (i = 0; i < len; i++) { + *out_dec += ((in_ascii[len-i-1] - '0') * multi); + multi *= 10; + } + + *out_dec *= flag; + return 0; +} + +fm_s32 trim_string(fm_s8 **start) +{ + fm_s8 *end = *start; + + /* Advance to non-space character */ + while (*(*start) == ' ') { + (*start)++; + } + + /* Move to end of string */ + while (*end != '\0') { + (end)++; + } + + /* Backup to non-space character */ + do { + end--; + } while ((end >= *start) && (*end == ' ')); + + /* Terminate string after last non-space character */ + *(++end) = '\0'; + return (end - *start); +} + +fm_s32 trim_path(fm_s8 **start) +{ + fm_s8 *end = *start; + + while (*(*start) == ' ') { + (*start)++; + } + + while (*end != '\0') { + (end)++; + } + + do { + end--; + } while ((end >= *start) && ((*end == ' ') || (*end == '\n') || (*end == '\r'))); + + *(++end) = '\0'; + return (end - *start); +} + +fm_s32 cfg_parser(fm_s8 *buffer, CFG_HANDLER handler, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + fm_s8 *p = buffer; + fm_s8 *group_start = NULL; + fm_s8 *key_start = NULL; + fm_s8 *value_start = NULL; + + enum fm_cfg_parser_state state = FM_CFG_STAT_NONE; + + FMR_ASSERT(p); + + for (p = buffer; *p != '\0'; p++) { + switch (state) { + case FM_CFG_STAT_NONE: { + if (*p == '[') { + //if we get char '[' in none state, it means a new group name start + state = FM_CFG_STAT_GROUP; + group_start = p + 1; + } else if (*p == COMMENT_CHAR) { + //if we get char '#' in none state, it means a new comment start + state = FM_CFG_STAT_COMMENT; + } else if (!isspace(*p) && (*p != '\n') && (*p != '\r')) { + //if we get an nonspace char in none state, it means a new key start + state = FM_CFG_STAT_KEY; + key_start = p; + } + + break; + } + case FM_CFG_STAT_GROUP: { + if (*p == ']') { + //if we get char ']' in group state, it means a group name complete + *p = '\0'; + //FIX_ME + //record group name + state = FM_CFG_STAT_NONE; + trim_string(&group_start); + //WCN_DBG(FM_NTC|MAIN, "g=%s\n", group_start); + } + + break; + } + case FM_CFG_STAT_COMMENT: { + if (*p == '\n') { + //if we get char '\n' in comment state, it means new line start + state = FM_CFG_STAT_NONE; + group_start = p + 1; + } + + break; + } + case FM_CFG_STAT_KEY: { + if (*p == DELIMIT_CHAR) { + //if we get char '=' in key state, it means a key name complete + *p = '\0'; + //FIX_ME + //record key name + state = FM_CFG_STAT_VALUE; + value_start = p + 1; + trim_string(&key_start); + //WCN_DBG(FM_NTC|MAIN, "k=%s\n", key_start); + } + + break; + } + case FM_CFG_STAT_VALUE: { + if (*p == '\n' || *p == '\r') { + //if we get char '\n' or '\r' in value state, it means a value complete + *p = '\0'; + //record value + trim_string(&value_start); + //WCN_DBG(FM_NTC|MAIN, "v=%s\n", value_start); + + if (handler) { + ret = handler(group_start, key_start, value_start, cfg); + } + + state = FM_CFG_STAT_NONE; + } + + break; + } + default: + break; + } + } + + return ret; +} + +fm_s32 cfg_item_match(fm_s8 *src_key, fm_s8 *src_val, fm_s8 *dst_key, fm_s32 *dst_val) +{ + fm_s32 ret = 0; + fm_u16 tmp_hex; + fm_s32 tmp_dec; + + //WCN_DBG(FM_NTC|MAIN,"src_key=%s,src_val=%s\n", src_key,src_val); + //WCN_DBG(FM_NTC|MAIN,"dst_key=%s\n", dst_key); + if (strcmp(src_key, dst_key) == 0) { + if (strncmp(src_val, "0x", strlen("0x")) == 0) { + src_val += strlen("0x"); + //WCN_DBG(FM_NTC|MAIN,"%s\n", src_val); + ret = ascii_to_hex(src_val, &tmp_hex); + + if (!ret) { + *dst_val = tmp_hex; + //WCN_DBG(FM_NTC|MAIN, "%s 0x%04x\n", dst_key, tmp_hex); + return 0; + } else { + //WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key); + return 1; + } + } else { + ret = ascii_to_dec(src_val, &tmp_dec); + + if (!ret /*&& ((0 <= tmp_dec) && (tmp_dec <= 0xFFFF))*/) { + *dst_val = tmp_dec; + //WCN_DBG(FM_NTC|MAIN, "%s %d\n", dst_key, tmp_dec); + return 0; + } else { + //WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key); + return 1; + } + } + } + //else + //{ + // WCN_DBG(FM_ERR | MAIN, "src_key!=dst_key\n"); + //} + + return -1; +} + +static fm_s32 cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg; + struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg; + + if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_L", &rx_cfg->long_ana_rssi_th))) {//FMR_RSSI_TH_L = 0x0301 + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_S", &rx_cfg->short_ana_rssi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_CQI_TH", &rx_cfg->cqi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_MR_TH", &rx_cfg->mr_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SMG_TH", &rx_cfg->smg_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_CH_SIZE", &rx_cfg->scan_ch_size))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_SORT", &rx_cfg->scan_sort))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SEEK_SPACE", &rx_cfg->seek_space))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND", &rx_cfg->band))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_L", &rx_cfg->band_freq_l))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_H", &rx_cfg->band_freq_h))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH", &rx_cfg->fake_ch[fm_index]))) { + fm_index += 1; + rx_cfg->fake_ch_num = (rx_cfg->fake_ch_num < fm_index) ? fm_index : rx_cfg->fake_ch_num; + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_RSSI", &rx_cfg->fake_ch_rssi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_DEEMPHASIS", &rx_cfg->deemphasis))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_OSC_FREQ", &rx_cfg->osc_freq))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_L", &tx_cfg->scan_hole_low))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_H", &tx_cfg->scan_hole_high))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMT_PWR_LVL_MAX", &tx_cfg->power_level))) { + return ret; + } else { + WCN_DBG(FM_WAR | MAIN, "invalid key\n"); + return -1; + } +} + +static fm_s32 fm_cust_config_default(fm_cust_cfg *cfg) +{ + FMR_ASSERT(cfg); +#if (!defined(MT6628_FM)&&!defined(MT6620_FM)) + + cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG; + cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT; + cfg->rx_cfg.cqi_th = FM_RX_CQI_TH; + cfg->rx_cfg.mr_th = FM_RX_MR_TH; + cfg->rx_cfg.smg_th = FM_RX_SMG_TH; + cfg->rx_cfg.scan_ch_size = FM_RX_SCAN_CH_SIZE; + cfg->rx_cfg.seek_space = FM_RX_SEEK_SPACE; + cfg->rx_cfg.band = FM_RX_BAND; + cfg->rx_cfg.band_freq_l = FM_RX_BAND_FREQ_L; + cfg->rx_cfg.band_freq_h = FM_RX_BAND_FREQ_H; + cfg->rx_cfg.scan_sort = FM_RX_SCAN_SORT_SELECT; + cfg->rx_cfg.fake_ch_num = FM_RX_FAKE_CH_NUM; + cfg->rx_cfg.fake_ch_rssi_th = FM_RX_FAKE_CH_RSSI; + cfg->rx_cfg.fake_ch[0] = FM_RX_FAKE_CH_1; + cfg->rx_cfg.fake_ch[1] = FM_RX_FAKE_CH_2; + cfg->rx_cfg.fake_ch[2] = FM_RX_FAKE_CH_3; + cfg->rx_cfg.fake_ch[3] = FM_RX_FAKE_CH_4; + cfg->rx_cfg.fake_ch[4] = FM_RX_FAKE_CH_5; + cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS; + + cfg->tx_cfg.scan_hole_low = FM_TX_SCAN_HOLE_LOW; + cfg->tx_cfg.scan_hole_high = FM_TX_SCAN_HOLE_HIGH; + cfg->tx_cfg.power_level = FM_TX_PWR_LEVEL_MAX; +#endif + return 0; +} + +static fm_s32 fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + fm_s8 *buf = NULL; + fm_s32 file_len = 0; + + if (!(buf = fm_zalloc(4096))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + return -ENOMEM; + } + + fm_index = 0; + + file_len = fm_file_read(filename, buf, 4096, 0); + + if (file_len <= 0) { + ret = -1; + goto out; + } + + ret = cfg_parser(buf, cfg_item_handler, cfg); + +out: + + if (buf) { + fm_free(buf); + } + + return ret; +} + +static fm_s32 fm_cust_config_print(fm_cust_cfg *cfg) +{ + fm_s32 i; + + WCN_DBG(FM_NTC | MAIN, "rssi_l:\t0x%04x\n", cfg->rx_cfg.long_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "rssi_s:\t0x%04x\n", cfg->rx_cfg.short_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "mr_th:\t0x%04x\n", cfg->rx_cfg.mr_th); + WCN_DBG(FM_NTC | MAIN, "cqi_th:\t0x%04x\n", cfg->rx_cfg.cqi_th); + WCN_DBG(FM_NTC | MAIN, "smg_th:\t0x%04x\n", cfg->rx_cfg.smg_th); + WCN_DBG(FM_NTC | MAIN, "scan_ch_size:\t%d\n", cfg->rx_cfg.scan_ch_size); + WCN_DBG(FM_NTC | MAIN, "seek_space:\t%d\n", cfg->rx_cfg.seek_space); + WCN_DBG(FM_NTC | MAIN, "band:\t%d\n", cfg->rx_cfg.band); + WCN_DBG(FM_NTC | MAIN, "band_freq_l:\t%d\n", cfg->rx_cfg.band_freq_l); + WCN_DBG(FM_NTC | MAIN, "band_freq_h:\t%d\n", cfg->rx_cfg.band_freq_h); + WCN_DBG(FM_NTC | MAIN, "scan_sort:\t%d\n", cfg->rx_cfg.scan_sort); + WCN_DBG(FM_NTC | MAIN, "fake_ch_num:\t%d\n", cfg->rx_cfg.fake_ch_num); + WCN_DBG(FM_NTC | MAIN, "fake_ch_rssi_th:\t%d\n", cfg->rx_cfg.fake_ch_rssi_th); + + for (i = 0; i < cfg->rx_cfg.fake_ch_num; i++) { + WCN_DBG(FM_NTC | MAIN, "fake_ch:\t%d\n", cfg->rx_cfg.fake_ch[i]); + } + + WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis); + WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq); + WCN_DBG(FM_NTC | MAIN, "scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low); + WCN_DBG(FM_NTC | MAIN, "scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high); + WCN_DBG(FM_NTC | MAIN, "power_level:\t%d\n", cfg->tx_cfg.power_level); + + return 0; +} +fm_s32 fm_cust_config(const fm_s8 *filepath) +{ + fm_s32 ret = 0; + fm_s8 *filep = NULL; + fm_s8 file_path[51] = {0}; + + fm_cust_config_default(&fm_config); + WCN_DBG(FM_NTC | MAIN, "FM default config\n"); + fm_cust_config_print(&fm_config); + + if (!filepath) { + filep = FM_CUST_CFG_PATH; + } else { + memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath)); + filep = file_path; + trim_path(&filep); + } + + ret = fm_cust_config_file(filep, &fm_config); + WCN_DBG(FM_NTC | MAIN, "FM cust config\n"); + fm_cust_config_print(&fm_config); + return ret; +} + +fm_u16 fm_cust_config_fetch(enum fm_cust_cfg_op op_code) +{ + fm_u16 tmp = 0; + fm_s32 i; + static fm_s32 fake_ch_idx = 0; + + switch (op_code) { + //For FM RX + case FM_CFG_RX_RSSI_TH_LONG: { + tmp = fm_config.rx_cfg.long_ana_rssi_th; + break; + } + case FM_CFG_RX_RSSI_TH_SHORT: { + tmp = fm_config.rx_cfg.short_ana_rssi_th; + break; + } + case FM_CFG_RX_CQI_TH: { + tmp = fm_config.rx_cfg.cqi_th; + break; + } + case FM_CFG_RX_MR_TH: { + tmp = fm_config.rx_cfg.mr_th; + break; + } + case FM_CFG_RX_SMG_TH: { + tmp = fm_config.rx_cfg.smg_th; + break; + } + case FM_CFG_RX_SCAN_CH_SIZE: { + tmp = fm_config.rx_cfg.scan_ch_size; + break; + } + case FM_CFG_RX_SEEK_SPACE: { + tmp = fm_config.rx_cfg.seek_space; + break; + } + case FM_CFG_RX_BAND: { + tmp = fm_config.rx_cfg.band; + break; + } + case FM_CFG_RX_BAND_FREQ_L: { + tmp = fm_config.rx_cfg.band_freq_l; + break; + } + case FM_CFG_RX_BAND_FREQ_H: { + tmp = fm_config.rx_cfg.band_freq_h; + break; + } + case FM_CFG_RX_SCAN_SORT: { + tmp = fm_config.rx_cfg.scan_sort; + break; + } + case FM_CFG_RX_FAKE_CH_NUM: { + tmp = fm_config.rx_cfg.fake_ch_num; + break; + } + case FM_CFG_RX_FAKE_CH: { + tmp = fm_config.rx_cfg.fake_ch[fake_ch_idx]; + i = (fm_config.rx_cfg.fake_ch_num > 0) ? fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX; + fake_ch_idx++; + fake_ch_idx = fake_ch_idx % i; + break; + } + case FM_CFG_RX_FAKE_CH_RSSI: { + tmp = fm_config.rx_cfg.fake_ch_rssi_th; + break; + } + case FM_CFG_RX_DEEMPHASIS: { + tmp = fm_config.rx_cfg.deemphasis; + break; + } + case FM_CFG_RX_OSC_FREQ: { + tmp = fm_config.rx_cfg.osc_freq; + break; + } + //For FM TX + case FM_CFG_TX_SCAN_HOLE_LOW: { + tmp = fm_config.tx_cfg.scan_hole_low; + break; + } + case FM_CFG_TX_SCAN_HOLE_HIGH: { + tmp = fm_config.tx_cfg.scan_hole_high; + break; + } + case FM_CFG_TX_PWR_LEVEL: { + tmp = fm_config.tx_cfg.power_level; + break; + } + default: + break; + } + + WCN_DBG(FM_DBG | MAIN, "cust cfg %d: 0x%04x\n", op_code, tmp); + return tmp; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c new file mode 100755 index 000000000000..23fd4e434b34 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c @@ -0,0 +1,55 @@ +/* mt6620_fm_eint.c + * + * (C) Copyright 2009 + * MediaTek + * Run + * + * WCN combo chip FM Radio Driver -- EINT functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_eint.h" + +fm_s32 fm_enable_eint(void) +{ + return 0; +} + +fm_s32 fm_disable_eint(void) +{ + return 0; +} + +fm_s32 fm_request_eint(void (*parser)(void)) +{ + WCN_DBG(FM_NTC|EINT,"%s\n", __func__); + + mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser); + + return 0; +} + +fm_s32 fm_eint_pin_cfg(fm_s32 mode) +{ + return 0; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_link.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_link.c new file mode 100755 index 000000000000..30a0ec0daecf --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_link.c @@ -0,0 +1,550 @@ +/* fm_link.c + * + * (C) Copyright 2012 + * MediaTek + * Hongcheng + * + * FM Radio Driver -- setup data link common part + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_link.h" +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#include "stp_exp.h" +#include "wmt_exp.h" +static struct fm_link_event *link_event; + +static struct fm_trace_fifo_t *cmd_fifo; + +static struct fm_trace_fifo_t *evt_fifo; + +static fm_s32 (*reset)(fm_s32 sta) = NULL; + +static void WCNfm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, + ENUM_WMTMSG_TYPE_T type, + void *buf, + unsigned int sz) +{ + //To handle reset procedure please + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((char *)&rst_msg, (char *)buf, sz); + WCN_DBG(FM_WAR | LINK, "[src=%d], [dst=%d], [type=%d], [buf=0x%x], [sz=%d], [max=%d]\n", src, dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_FM) && (type == WMTMSG_TYPE_RESET)) { + if (rst_msg == WMTRSTMSG_RESET_START) { + WCN_DBG(FM_WAR | LINK, "FM restart start!\n"); + if (reset) { + reset(1); + } + + } else if (rst_msg == WMTRSTMSG_RESET_END) { + WCN_DBG(FM_WAR | LINK, "FM restart end!\n"); + if (reset) { + reset(0); + } + } + } + } else { + /*message format invalid*/ + WCN_DBG(FM_WAR | LINK, "message format invalid!\n"); + } +} + + +fm_s32 fm_link_setup(void* data) +{ + fm_s32 ret = 0; + + if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) { + WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n"); + return -1; + } + + link_event->ln_event = fm_flag_event_create("ln_evt"); + + if (!link_event->ln_event) { + WCN_DBG(FM_ALT | LINK, "create mt6620_ln_event failed\n"); + fm_free(link_event); + return -1; + } + + fm_flag_event_get(link_event->ln_event); + + + WCN_DBG(FM_NTC | LINK, "fm link setup\n"); + + cmd_fifo = fm_trace_fifo_create("cmd_fifo"); + if (!cmd_fifo) { + WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n"); + ret = -1; + goto failed; + } + + evt_fifo = fm_trace_fifo_create("evt_fifo"); + if (!evt_fifo) { + WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n"); + ret = -1; + goto failed; + } + + reset = data; // get whole chip reset cb + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, WCNfm_wholechip_rst_cb); + return 0; + +failed: + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + return ret; +} + +fm_s32 fm_link_release(void) +{ + + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + WCN_DBG(FM_NTC | LINK, "fm link release\n"); + return 0; +} + +/* + * fm_ctrl_rx + * the low level func to read a rigister + * @addr - rigister address + * @val - the pointer of target buf + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val) +{ + return 0; +} + +/* + * fm_ctrl_tx + * the low level func to write a rigister + * @addr - rigister address + * @val - value will be writed in the rigister + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val) +{ + return 0; +} + +/* + * fm_cmd_tx() - send cmd to FM firmware and wait event + * @buf - send buffer + * @len - the length of cmd + * @mask - the event flag mask + * @ cnt - the retry conter + * @timeout - timeout per cmd + * Return 0, if success; error code, if failed + */ +fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result)) +{ + fm_s32 ret_time = 0; + struct task_struct *task = current; + struct fm_trace_t trace; + + if ((NULL == buf) || (len < 0) || (0 == mask) + || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) { + WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n"); + return -FM_EPARA; + } + + FM_EVENT_CLR(link_event->ln_event, mask); + +#ifdef FM_TRACE_ENABLE + trace.type = buf[0]; + trace.opcode = buf[1]; + trace.len = len - 4; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len); +#endif + +sw_retry: + +#ifdef FM_TRACE_ENABLE + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + + //send cmd to FM firmware + if ((ret_time = mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX)) <= 0) + { + WCN_DBG(FM_EMG | LINK, "send data over stp failed[%d]\n",ret_time); + return -FM_ELINK; + } + + //wait the response form FM firmware + ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout); + + if (!ret_time) { + if (0 < cnt--) { + WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid); + fm_print_cmd_fifo(); + fm_print_evt_fifo(); + return -FM_EFW; + goto sw_retry; //retry if timeout and retry cnt > 0 + } else { + WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n"); + return -FM_EFW; + } + } + + FM_EVENT_CLR(link_event->ln_event, mask); + + if (callback) { + callback(&link_event->result); + } + + return 0; +} + +fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32)) +{ + fm_s32 len; + fm_s32 i = 0; + fm_u8 opcode = 0; + fm_u16 length = 0; + fm_u8 ch; + fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps + static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE; + struct fm_trace_t trace; + struct task_struct *task = current; + + len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX); + WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]); + + while (i < len) { + ch = rx_buf[i]; + + switch (state) { + case FM_TASK_RX_PARSER_PKT_TYPE: + + if (ch == FM_TASK_EVENT_PKT_TYPE) { + if ((i + 5) < RX_BUF_SIZE) { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]); + } else { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]); + } + + state = FM_TASK_RX_PARSER_OPCODE; + } else { + WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch); + } + + i++; + break; + + case FM_TASK_RX_PARSER_OPCODE: + i++; + opcode = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_1; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_1: + i++; + length = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_2; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_2: + i++; + length |= (fm_u16)(ch << 0x8); + +#ifdef FM_TRACE_ENABLE + trace.type = FM_TASK_EVENT_PKT_TYPE; + trace.opcode = opcode; + trace.len = length; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length); + + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + if (length > 0) { + state = FM_TASK_RX_PARSER_PKT_PAYLOAD; + } else { + state = FM_TASK_RX_PARSER_PKT_TYPE; + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + } + + break; + + case FM_TASK_RX_PARSER_PKT_PAYLOAD: + + switch (opcode) { + case FM_TUNE_OPCODE: + + if ((length == 1) && (rx_buf[i] == 1)) { + FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE); + } + + break; + + case FM_SOFT_MUTE_TUNE_OPCODE: + + if (length >= 2) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length); + FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE); + } + break; + + case FM_SEEK_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz + } + + FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE); + break; + + case FM_SCAN_OPCODE: + + //check if the result data is long enough + if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) { + WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + return 0; + } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE); + } else { + fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + } + + break; + + case FSPI_READ_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8)); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + case RDS_RX_DATA_OPCODE: + + //check if the rds data is long enough + if ((RX_BUF_SIZE - i) < length) { + WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + //copy rds data to rds buf + fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length); + + /*Handle the RDS data that we get*/ + if (rds_parser) { + rds_parser(&link_event->result.rds_rx_result, length); + } else { + WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n"); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + default: + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + state = FM_TASK_RX_PARSER_PKT_TYPE; + i += length; + break; + + default: + break; + } + } + + return 0; +} + +fm_bool fm_wait_stc_done(fm_u32 sec) +{ + return fm_true; +} + +fm_s32 fm_force_active_event(fm_u32 mask) +{ + fm_u32 flag; + + flag = FM_EVENT_GET(link_event->ln_event); + WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag); + flag = FM_EVENT_SEND(link_event->ln_event, mask); + WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag); + + return 0; +} + + +extern fm_s32 fm_print_cmd_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(cmd_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "trace\n"); + } +#endif + + return 0; +} + +extern fm_s32 fm_print_evt_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(evt_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(evt_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name); + } +#endif + + return 0; +} +#endif + +fm_s32 fm_trace_in(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra) +{ + FMR_ASSERT(new_tra); + + if (thiz->len < thiz->size) { + fm_memcpy(&(thiz->trace[thiz->in]), new_tra, sizeof(struct fm_trace_t)); + thiz->trace[thiz->in].time = jiffies; + thiz->in = (thiz->in + 1) % thiz->size; + thiz->len++; + //WCN_DBG(FM_DBG | RDSC, "add a new tra[len=%d]\n", thiz->len); + } else { + WCN_DBG(FM_WAR | RDSC, "tra buf is full\n"); + return -FM_ENOMEM; + } + + return 0; +} + +fm_s32 fm_trace_out(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra) +{ + if (thiz->len > 0) { + if (dst_tra) { + fm_memcpy(dst_tra, &(thiz->trace[thiz->out]), sizeof(struct fm_trace_t)); + fm_memset(&(thiz->trace[thiz->out]), 0, sizeof(struct fm_trace_t)); + } + thiz->out = (thiz->out + 1) % thiz->size; + thiz->len--; + //WCN_DBG(FM_DBG | RDSC, "del a tra[len=%d]\n", thiz->len); + } else { + WCN_DBG(FM_WAR | RDSC, "tra buf is empty\n"); + } + + return 0; +} + +fm_bool fm_trace_is_full(struct fm_trace_fifo_t *thiz) +{ + return (thiz->len == thiz->size) ? fm_true : fm_false; +} + +fm_bool fm_trace_is_empty(struct fm_trace_fifo_t *thiz) +{ + return (thiz->len == 0) ? fm_true : fm_false; +} + + +struct fm_trace_fifo_t* fm_trace_fifo_create(const fm_s8 *name) +{ + struct fm_trace_fifo_t *tmp; + + if (!(tmp = fm_zalloc(sizeof(struct fm_trace_fifo_t)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_trace_fifo) -ENOMEM\n"); + return NULL; + } + + fm_memcpy(tmp->name, name, 20); + tmp->size = FM_TRACE_FIFO_SIZE; + tmp->in = 0; + tmp->out = 0; + tmp->len = 0; + tmp->trace_in = fm_trace_in; + tmp->trace_out = fm_trace_out; + tmp->is_full = fm_trace_is_full; + tmp->is_empty = fm_trace_is_empty; + + WCN_DBG(FM_NTC | LINK, "%s created\n", tmp->name); + + return tmp; +} + + +fm_s32 fm_trace_fifo_release(struct fm_trace_fifo_t *fifo) +{ + if (fifo) { + WCN_DBG(FM_NTC | LINK, "%s released\n", fifo->name); + fm_free(fifo); + } + + return 0; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_main.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_main.c new file mode 100755 index 000000000000..1637197fba30 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_main.c @@ -0,0 +1,2892 @@ +/* fm_main.c + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * FM Radio Driver -- main functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include "fm_main.h" +#include "fm_config.h" +//#include "fm_cust_cfg.h" +#include "wmt_exp.h" +//fm main data structure +static struct fm *g_fm_struct = NULL; +//we must get low level interface first, when add a new chip, the main effort is this interface +static struct fm_lowlevel_ops fm_low_ops; +#ifdef MT6620_FM +static struct fm_lowlevel_ops MT6620fm_low_ops; +#endif +#ifdef MT6628_FM +static struct fm_lowlevel_ops MT6628fm_low_ops; +#endif +//MTK FM Radio private advanced features +#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM)) +static struct fm_priv priv_adv; +#endif +//mutex for char device ops +static struct fm_lock *fm_ops_lock; +//mutex for RDS parsing and read result +static struct fm_lock *fm_read_lock; +//for get rds block counter +static struct fm_lock *fm_rds_cnt; +//mutex for fm timer, RDS reset +static struct fm_lock *fm_timer_lock; +static struct fm_lock *fm_rxtx_lock;//protect FM RX TX mode switch +static struct fm_lock *fm_rtc_mutex;//protect FM GPS RTC drift info + +static struct fm_timer *fm_timer_sys; + +static struct fm_i2s_info fm_i2s_inf = { + .status = 0, //i2s off + .mode = 0, //slave mode + .rate = 48000, //48000 sample rate +}; + +static fm_bool scan_stop_flag = fm_false; +static struct fm_gps_rtc_info gps_rtc_info; + +//RDS reset related functions +static fm_u16 fm_cur_freq_get(void); +static fm_s32 fm_cur_freq_set(fm_u16 new_freq); +static enum fm_op_state fm_op_state_get(struct fm *fmp); +static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta); +static void fm_timer_func(unsigned long data); +static void fmtx_timer_func(unsigned long data); + +static void fm_enable_rds_BlerCheck(struct fm *fm); +static void fm_disable_rds_BlerCheck(void); +static void fm_rds_reset_work_func(unsigned long data); +//when interrupt be triggered by FM chip, fm_eint_handler will first be executed +//then fm_eint_handler will schedule fm_eint_work_func to run +static void fm_eint_handler(void); +static void fm_eint_work_func(unsigned long data); +static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size); +static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops); +static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops); + +static fm_s32 pwrdown_flow(struct fm *fm); + +static fm_u16 fm_cur_freq_get(void) +{ + return g_fm_struct ? g_fm_struct->cur_freq : 0; +} + +static fm_s32 fm_cur_freq_set(fm_u16 new_freq) +{ + if (g_fm_struct) + g_fm_struct->cur_freq = new_freq; + + return 0; +} + +static enum fm_op_state fm_op_state_get(struct fm *fmp) +{ + if (fmp) { + WCN_DBG(FM_DBG | MAIN, "op state get %d\n", fmp->op_sta); + return fmp->op_sta; + } else { + WCN_DBG(FM_ERR | MAIN, "op state get para error\n"); + return FM_STA_UNKOWN; + } +} + +static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta) +{ + if (fmp && (sta < FM_STA_MAX)) { + fmp->op_sta = sta; + WCN_DBG(FM_DBG | MAIN, "op state set to %d\n", sta); + return fmp->op_sta; + } else { + WCN_DBG(FM_ERR | MAIN, "op state set para error, %d\n", sta); + return FM_STA_UNKOWN; + } +} + +enum fm_pwr_state fm_pwr_state_get(struct fm *fmp) +{ + if (fmp) { + WCN_DBG(FM_DBG | MAIN, "pwr state get %d\n", fmp->pwr_sta); + return fmp->pwr_sta; + } else { + WCN_DBG(FM_ERR | MAIN, "pwr state get para error\n"); + return FM_PWR_MAX; + } +} + +enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta) +{ + if (fmp && (sta < FM_PWR_MAX)) { + fmp->pwr_sta = sta; + WCN_DBG(FM_NTC | MAIN, "pwr state set to %d\n", sta); + return fmp->pwr_sta; + } else { + WCN_DBG(FM_ERR | MAIN, "pwr state set para error, %d\n", sta); + return FM_PWR_MAX; + } +} + +static volatile fm_s32 subsys_rst_state = FM_SUBSYS_RST_OFF; + +fm_s32 fm_sys_state_get(struct fm *fmp) +{ + return subsys_rst_state; +} + +fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta) +{ + if ((sta >= FM_SUBSYS_RST_OFF) && (sta < FM_SUBSYS_RST_MAX)) { + WCN_DBG(FM_NTC | MAIN, "sys state set from %d to %d\n", subsys_rst_state, sta); + subsys_rst_state = sta; + } else { + WCN_DBG(FM_ERR | MAIN, "sys state set para error, %d\n", sta); + } + + return subsys_rst_state; +} + + +fm_s32 fm_subsys_reset(struct fm *fm) +{ + //check if we are resetting + if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) { + WCN_DBG(FM_NTC | MAIN, "subsys reset is ongoing\n"); + goto out; + } + + FMR_ASSERT(fm); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk); + +out: + return 0; +} + + +fm_s32 fm_wholechip_rst_cb(fm_s32 sta) +{ + struct fm *fm = g_fm_struct; + + if (!fm) return 0; + + if (sta == 1) { + if (fm_sys_state_get(fm) == FM_SUBSYS_RST_OFF) { + fm_sys_state_set(fm, FM_SUBSYS_RST_START); + } + } else { + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk); + } + return 0; +} + + +fm_s32 fm_open(struct fm *fmp) +{ + fm_s32 ret = 0; +#if (defined(MT6620_FM)||defined(MT6628_FM)) + fm_s32 chipid; +#endif + FMR_ASSERT(fmp); + if (current->pid == 1) + return 0; + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + //makesure fmp->ref >= 0 + fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref; + fmp->ref++; + + if ((fmp->ref > 0) && (fmp->chipon == fm_false)) + { +#if (defined(MT6620_FM)||defined(MT6628_FM)) + chipid = mtk_wcn_wmt_chipid_query(); + WCN_DBG(FM_NTC | MAIN, "wmt chip id=0x%x\n",chipid); + if(chipid == 0x6628)//get WCN chip ID + { +#ifdef MT6628_FM + fm_low_ops = MT6628fm_low_ops; + fmp->chip_id = 0x6628; + WCN_DBG(FM_NTC | MAIN, "get 6628 low ops\n"); +#endif + } + else if(chipid == 0x6620) + { +#ifdef MT6620_FM + fm_low_ops = MT6620fm_low_ops; + fmp->chip_id = 0x6620; + WCN_DBG(FM_NTC | MAIN, "get 6620 low ops\n"); +#endif + } +#endif + if(fm_low_ops.bi.pwron == NULL) + { + WCN_DBG(FM_NTC | MAIN, "get fm_low_ops fail\n"); + fmp->ref--; + ret = -ENODEV; + goto out; + } + + ret = fm_low_ops.bi.pwron(0); + if (ret) { + fmp->ref--; + ret = -ENODEV; + goto out; + } + + fm_eint_pin_cfg(FM_EINT_PIN_EINT_MODE); + fm_request_eint(fm_eint_handler); + fmp->chipon = fm_true; + } + +out: + WCN_DBG(FM_NTC | MAIN, "fm->ref:%d\n", fmp->ref); + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_close(struct fm *fmp) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fmp); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + fmp->ref--; + + if (fmp->ref == 0) { + pwrdown_flow(fmp); + if (fmp->chipon == fm_true) { + fm_eint_pin_cfg(FM_EINT_PIN_GPIO_MODE); + fm_low_ops.bi.pwroff(0); + fmp->chipon = fm_false; + } + } + + //makesure fm->ref >= 0 + fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref; + WCN_DBG(FM_NTC | MAIN, "fmp->ref:%d\n", fmp->ref); + FM_UNLOCK(fm_ops_lock); + + return ret; +} +/* +fm_s32 fm_flush(struct fm *fmp) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fmp); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (FM_PWR_OFF == fm_pwr_state_get(fmp)) + { + WCN_DBG(FM_NTC | MAIN, "should power off combo!\n"); + if (fmp->chipon == fm_true) + { + fm_low_ops.bi.pwroff(0); + fmp->chipon = fm_false; + } + } + WCN_DBG(FM_NTC | MAIN, "fm_flush done\n"); + FM_UNLOCK(fm_ops_lock); + + return ret; +} +*/ +fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len) +{ + fm_s32 copy_len = 0, left = 0; + copy_len = sizeof(rds_t); + +RESTART: + + if (FM_EVENT_GET(fmp->rds_event) == FM_RDS_DATA_READY) { + if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK); + + if ((left = copy_to_user((void *)dst, fmp->pstRDSData, (unsigned long)copy_len))) { + WCN_DBG(FM_ALT | MAIN, "fm_read copy failed\n"); + } else { + fmp->pstRDSData->event_status = 0x0000; + } + + WCN_DBG(FM_DBG | MAIN, "fm_read copy len:%d\n", (copy_len - left)); + + FM_EVENT_RESET(fmp->rds_event); + FM_UNLOCK(fm_read_lock); + } else { + if (FM_EVENT_WAIT(fmp->rds_event, FM_RDS_DATA_READY) == 0) { + WCN_DBG(FM_DBG | MAIN, "fm_read wait ok\n"); + goto RESTART; + } else { + WCN_DBG(FM_ALT | MAIN, "fm_read wait err\n"); + return 0; + } + } + + return (copy_len - left); +} + +fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.pwron); + FMR_ASSERT(fm_low_ops.bi.pwrupseq); + FMR_ASSERT(fm_low_ops.bi.low_pwr_wa); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + //for normal case + if (fm->chipon == fm_false) { + fm_low_ops.bi.pwron(0); + fm->chipon = fm_true; + } + + if (FM_PWR_RX_ON == fm_pwr_state_get(fm)) { + WCN_DBG(FM_NTC | MAIN, "already pwron!\n"); + goto out; + } + else if(FM_PWR_TX_ON == fm_pwr_state_get(fm)) + { + //if Tx is on, we need pwr down TX first + ret = fm_powerdowntx(fm); + if(ret) + { + WCN_DBG(FM_ERR | MAIN,"FM pwr down Tx fail!\n"); + return ret; + } + } + + fm_pwr_state_set(fm, FM_PWR_RX_ON); + + //execute power on sequence + ret = fm_low_ops.bi.pwrupseq(&fm->chip_id, &fm->device_id); + + if (ret) { + goto out; + } + + fm_enable_eint(); + + WCN_DBG(FM_DBG | MAIN, "pwron ok\n"); + fm_cur_freq_set(parm->freq); + + parm->err = FM_SUCCESS; + fm_low_ops.bi.low_pwr_wa(1); + + fm->vol = 15; + if(fm_low_ops.ri.rds_bci_get) + { + fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0); + fm_timer_sys->start(fm_timer_sys); + WCN_DBG(FM_NTC | MAIN, "start timer ok\n"); + } + else + { + WCN_DBG(FM_NTC | MAIN, "start timer fail!!!\n"); + } + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* + * fm_powerup_tx + */ +fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.pwron); + FMR_ASSERT(fm_low_ops.bi.pwrupseq_tx); + + if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) { + WCN_DBG(FM_NTC | MAIN, "already pwron!\n"); + parm->err = FM_BADSTATUS; + goto out; + } + else if(FM_PWR_RX_ON == fm_pwr_state_get(fm)) + { + //if Rx is on, we need pwr down first + ret = fm_powerdown(fm); + if(ret) + { + WCN_DBG(FM_ERR | MAIN,"FM pwr down Rx fail!\n"); + goto out; + } + } + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + //for normal case + if (fm->chipon == fm_false) { + fm_low_ops.bi.pwron(0); + fm->chipon = fm_true; + } + + fm_pwr_state_set(fm, FM_PWR_TX_ON); + ret = fm_low_ops.bi.pwrupseq_tx(); + + if(ret) + { + parm->err = FM_FAILED; + } + else + { + parm->err = FM_SUCCESS; + } + fm_cur_freq_set(parm->freq); + //if(fm_low_ops.ri.rds_bci_get) + { + fm_timer_sys->count = 0; + fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_ENABLE; + fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_ENABLE; + fm_timer_sys->tx_desense_en = FM_TX_DESENSE_ENABLE; + + fm_timer_sys->init(fm_timer_sys, fmtx_timer_func, (unsigned long)g_fm_struct,FM_TIMER_TIMEOUT_MIN, 0); + fm_timer_sys->start(fm_timer_sys); + WCN_DBG(FM_NTC | MAIN, "start timer ok\n"); + } + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +static fm_s32 pwrdown_flow(struct fm *fm) +{ + fm_s32 ret = 0; + FMR_ASSERT(fm_low_ops.ri.rds_onoff); + FMR_ASSERT(fm_low_ops.bi.pwrdownseq); + FMR_ASSERT(fm_low_ops.bi.low_pwr_wa); + if (FM_PWR_OFF == fm_pwr_state_get(fm)) { + WCN_DBG(FM_NTC | MAIN, "already pwroff!\n"); + goto out; + } + /*if(fm_low_ops.ri.rds_bci_get) + { + fm_timer_sys->stop(fm_timer_sys); + WCN_DBG(FM_NTC | MAIN, "stop timer ok\n"); + } + else + { + WCN_DBG(FM_NTC | MAIN, "stop timer fail!!!\n"); + }*/ + + //Disable all interrupt + fm_disable_rds_BlerCheck(); + fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false); + fm_disable_eint(); + + fm_pwr_state_set(fm, FM_PWR_OFF); + + //execute power down sequence + ret = fm_low_ops.bi.pwrdownseq(); + + fm_low_ops.bi.low_pwr_wa(0); + WCN_DBG(FM_ALT | MAIN, "pwrdown_flow exit\n"); + +out: + return ret; +} + +fm_s32 fm_powerdown(struct fm *fm) +{ + fm_s32 ret = 0; + if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) + { + ret = fm_powerdowntx(fm); + } + else + { + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + if (FM_LOCK(fm_rxtx_lock)) return(-FM_ELOCK); + + ret = pwrdown_flow(fm); + + FM_UNLOCK(fm_rxtx_lock); + FM_UNLOCK(fm_ops_lock); + } + return ret; +} + +fm_s32 fm_powerdowntx(struct fm *fm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.pwrdownseq_tx); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + if (FM_LOCK(fm_rxtx_lock)) return (-FM_ELOCK); + + if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) + { + if (FM_LOCK(fm_timer_lock)) return (-FM_ELOCK); + fm_timer_sys->stop(fm_timer_sys); + FM_UNLOCK(fm_timer_lock); + fm_timer_sys->count = 0; + fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_DISABLE; + fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_DISABLE; + fm_timer_sys->tx_desense_en = FM_TX_DESENSE_DISABLE; + + fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false); + //execute power down sequence + ret = fm_low_ops.bi.pwrdownseq(); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "pwrdown tx 1 fail\n"); + } + else + { + ret = fm_low_ops.bi.pwrdownseq_tx(); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "pwrdown tx 2 fail\n"); + } + } + fm_pwr_state_set(fm, FM_PWR_OFF); + WCN_DBG(FM_NTC | MAIN, "pwrdown tx ok\n"); + } + + FM_UNLOCK(fm_rxtx_lock); + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm) +{ + fm_s32 ret = 0; + fm_u16 seekdir, space; + + FMR_ASSERT(fm_low_ops.bi.seek); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + parm->err = FM_BADSTATUS; + ret = -EPERM; + goto out; + } + + if (parm->space == FM_SPACE_100K) { + space = 0x0002; + } else if (parm->space == FM_SPACE_50K) { + space = 0x0001; + } else if (parm->space == FM_SPACE_200K) { + space = 0x0004; + } else { + //default + space = 0x0002; + } + + if (parm->band == FM_BAND_UE) { + fm->min_freq = FM_UE_FREQ_MIN; + fm->max_freq = FM_UE_FREQ_MAX; + } else if (parm->band == FM_BAND_JAPANW) { + fm->min_freq = FM_JP_FREQ_MIN; + fm->max_freq = FM_JP_FREQ_MAX; + } else if (parm->band == FM_BAND_SPECIAL) { + fm->min_freq = FM_RX_BAND_FREQ_L; + fm->max_freq = FM_RX_BAND_FREQ_H; + } else { + WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band); + parm->err = FM_EPARM; + ret = -EPERM; + goto out; + } + + if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) { + WCN_DBG(FM_ALT | MAIN, "freq:%d out of range\n", parm->freq); + parm->err = FM_EPARM; + ret = -EPERM; + goto out; + } + + if (parm->seekdir == FM_SEEK_UP) { + seekdir = FM_SEEK_UP; + } else { + seekdir = FM_SEEK_DOWN; + } + + fm_op_state_set(fm, FM_STA_SEEK); + + // seek successfully + if (fm_true == fm_low_ops.bi.seek(fm->min_freq, fm->max_freq, &(parm->freq), seekdir, space)) { + parm->err = FM_SUCCESS; + } else { + parm->err = FM_SEEK_FAILED; + ret = -EPERM; + } + + if ((parm->space != FM_SPACE_50K) && (1 == fm_get_channel_space(parm->freq))) + { + parm->freq /= 10; //(8750 / 10) = 875 + } + + fm_op_state_set(fm, FM_STA_PLAY); +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/*********************************************************** +Function: fm_tx_scan() + +Description: get the valid channels for fm tx function + +Para: fm--->fm driver global info + parm--->input/output paramater + +Return: 0, if success; error code, if failed +***********************************************************/ +fm_s32 fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm) +{ + fm_s32 ret = 0; + fm_u16 scandir = 0; + fm_u16 space = FM_SPACE_100K; + + FMR_ASSERT(fm_low_ops.bi.tx_scan); + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm->chipon != fm_true) + { + parm->err = FM_BADSTATUS; + ret=-EPERM; + WCN_DBG(FM_ERR | MAIN, "tx scan chip not on\n"); + goto out; + } + switch(parm->scandir){ + case FM_TX_SCAN_UP: + scandir = 0; + break; + case FM_TX_SCAN_DOWN: + scandir = 1; + break; + default: + scandir = 0; + break; + } + + /*if (parm->space == FM_SPACE_100K) { + space = 2; + } else if (parm->space == FM_SPACE_50K) { + space = 1; + } else if (parm->space == FM_SPACE_200K) { + space = 4; + } else { + //default + space = 2; + }*/ + + if (parm->band == FM_BAND_UE) { + fm->min_freq = FM_UE_FREQ_MIN; + fm->max_freq = FM_UE_FREQ_MAX; + } else if (parm->band == FM_BAND_JAPANW) { + fm->min_freq = FM_JP_FREQ_MIN; + fm->max_freq = FM_JP_FREQ_MAX; + } else if (parm->band == FM_BAND_SPECIAL) { + fm->min_freq = FM_FREQ_MIN; + fm->max_freq = FM_FREQ_MAX; + } else + { + WCN_DBG(FM_ERR| MAIN,"band:%d out of range\n", parm->band); + parm->err = FM_EPARM; + ret=-EPERM; + goto out; + } + + if (unlikely((parm->freq < fm->min_freq) || (parm->freq > fm->max_freq))){ + parm->err = FM_EPARM; + ret=-EPERM; + goto out; + } + + if (unlikely(parm->ScanTBLSize < TX_SCAN_MIN || parm->ScanTBLSize > TX_SCAN_MAX)){ + parm->err = FM_EPARM; + ret=-EPERM; + goto out; + } + + ret = fm_low_ops.bi.anaswitch(FM_ANA_SHORT); + if(ret){ + WCN_DBG(FM_ERR | MAIN,"switch to short ana failed\n"); + goto out; + } + + //do tx scan + if(!(ret = fm_low_ops.bi.tx_scan(fm->min_freq, fm->max_freq, &(parm->freq), + parm->ScanTBL, &(parm->ScanTBLSize), scandir, space))){ + parm->err = FM_SUCCESS; + }else{ + WCN_DBG(FM_ERR | MAIN,"fm_tx_scan failed\n"); + parm->err = FM_SCAN_FAILED; + } +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_scan(struct fm *fm, struct fm_scan_parm *parm) +{ + fm_s32 ret = 0; + fm_u16 scandir = FM_SEEK_UP, space; + + FMR_ASSERT(fm_low_ops.bi.scan); + WCN_DBG(FM_NTC | MAIN, "fm_scan:start\n"); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + parm->err = FM_BADSTATUS; + ret = -EPERM; + goto out; + } + + if (parm->space == FM_SPACE_100K) { + space = 0x0002; + } else if (parm->space == FM_SPACE_50K) { + space = 0x0001; + } else if (parm->space == FM_SPACE_200K) { + space = 0x0004; + } else { + //default + space = 0x0002; + } + + if (parm->band == FM_BAND_UE) { + fm->min_freq = FM_UE_FREQ_MIN; + fm->max_freq = FM_UE_FREQ_MAX; + } else if (parm->band == FM_BAND_JAPANW) { + fm->min_freq = FM_JP_FREQ_MIN; + fm->max_freq = FM_JP_FREQ_MAX; + } else if (parm->band == FM_BAND_SPECIAL) { + fm->min_freq = FM_RX_BAND_FREQ_L; + fm->max_freq = FM_RX_BAND_FREQ_H; + } else { + WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band); + parm->err = FM_EPARM; + ret = -EPERM; + goto out; + } + + fm_op_state_set(fm, FM_STA_SCAN); + scan_stop_flag = fm_false; + + if (fm_true == fm_low_ops.bi.scan(fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)) { + parm->err = FM_SUCCESS; + } else { + WCN_DBG(FM_ALT | MAIN, "fm_scan failed\n"); + parm->err = FM_SEEK_FAILED; + ret = -EPERM; + } + + fm_op_state_set(fm, FM_STA_STOP); + +out: + FM_UNLOCK(fm_ops_lock); + WCN_DBG(FM_NTC | MAIN, "fm_scan:done\n"); + return ret; +} + + +#define SCAN_SEG_LEN 250 +static struct fm_cqi cqi_buf[SCAN_SEG_LEN]; + +fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm) +{ + fm_s32 ret = 0; + fm_s32 tmp; + fm_s32 cnt, seg; + fm_s32 i, j; + fm_s32 start_freq, end_freq; + fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip + fm_u16 tbl_size = FM_SCANTBL_SIZE; + fm_u16 tmp_freq = 0; + fm_s32 chl_cnt; + fm_s32 ch_offset, step, tmp_val; + fm_u16 space_idx = 0x0002; + + fm_s32 cqi_cnt, cqi_idx; + fm_s8 *buf = (fm_s8*)cqi_buf; + + FMR_ASSERT(fm_low_ops.bi.scan); + FMR_ASSERT(fm_low_ops.bi.cqi_get); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + // caculate channel number, get segment count + cnt = (parm->upper - parm->lower) / parm->space + 1; //Eg, (10800 - 8750) / 5 = 411 + seg = (cnt / SCAN_SEG_LEN) + ((cnt % SCAN_SEG_LEN) ? 1 : 0); //Eg, (411 / 200) + ((411 % 200) ? 1 : 0) = 2 + 1 = 3 + + WCN_DBG(FM_NTC | MAIN, "total ch %d, seg %d\n", cnt, seg); + + // alloc memory + tmp = cnt * sizeof(struct fm_ch_rssi*); + if (parm->sr_size < tmp) { + if (parm->sr.ch_rssi_buf) { + fm_free(parm->sr.ch_rssi_buf); + parm->sr.ch_rssi_buf = NULL; + } + parm->sr_size = tmp; + } + + if (!parm->sr.ch_rssi_buf) { + parm->sr.ch_rssi_buf = (struct fm_ch_rssi*)fm_zalloc(parm->sr_size); + if (!parm->sr.ch_rssi_buf) { + WCN_DBG(FM_ERR | MAIN, "scan alloc mem failed\n"); + parm->sr_size = 0; + return -2; + } + } + + if (parm->space == 5) { + space_idx = 0x0001; // 50Khz + } else if (parm->space == 10) { + space_idx = 0x0002; // 100Khz + } else if (parm->space == 20) { + space_idx = 0x0004; // 200Khz + } + + + fm_op_state_set(fm, FM_STA_SCAN); + + // do scan + chl_cnt = 0; + for (i = 0; (i < seg) && (fm_false == scan_stop_flag); i++) { + cqi_cnt = 0; + cqi_idx = 0; + + start_freq = parm->lower + SCAN_SEG_LEN * parm->space * i; + end_freq = parm->lower + SCAN_SEG_LEN * parm->space * (i + 1) - parm->space; + end_freq = (end_freq > parm->upper) ? parm->upper : end_freq; + + WCN_DBG(FM_NTC | MAIN, "seg %d, start %d, end %d\n", i, start_freq, end_freq); + if(fm_false == fm_low_ops.bi.scan(start_freq, end_freq, &tmp_freq, scan_tbl, &tbl_size, FM_SEEK_UP, space_idx)) { + ret = -1; + goto out; + } + + // get channel count + for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) { + if (scan_tbl[ch_offset] == 0) + continue; + for (step = 0; step < 16; step++) { + if (scan_tbl[ch_offset] & (1 << step)) { + tmp_val = start_freq + (ch_offset * 16 + step) * parm->space; + if (tmp_val <= end_freq) { + // record valid result channel + WCN_DBG(FM_NTC | MAIN, "freq %d\n", tmp_val); + parm->sr.ch_rssi_buf[chl_cnt].freq = tmp_val; + chl_cnt++; + cqi_cnt++; + } + } + } + } + + // get cqi + if(fm_low_ops.bi.cqi_get) + { + tmp = cqi_cnt; + while ((cqi_cnt > 0) && (fm_false == scan_stop_flag)) { + ret = fm_low_ops.bi.cqi_get(buf + (16 * sizeof(struct fm_cqi) * cqi_idx), + sizeof(cqi_buf) - (16 * sizeof(struct fm_cqi) * cqi_idx)); + if (ret) { + goto out; + } + + cqi_cnt -= 16; + cqi_idx++; + } + cqi_cnt = tmp; + + // fill cqi to result buffer + for (j = 0; j < cqi_cnt; j++) { + tmp = chl_cnt - cqi_cnt + j; // target pos + parm->sr.ch_rssi_buf[tmp].freq = (fm_u16)cqi_buf[j].ch; + parm->sr.ch_rssi_buf[tmp].rssi= cqi_buf[j].rssi; + WCN_DBG(FM_NTC | MAIN, "idx %d, freq %d, rssi %d \n", tmp, parm->sr.ch_rssi_buf[tmp].freq, parm->sr.ch_rssi_buf[tmp].rssi); + } + } + //6620 won't get rssi in scan new + //else if(fm_low_ops.bi.rssiget) + } + + fm_op_state_set(fm, FM_STA_STOP); + +out: + scan_stop_flag = fm_false; + FM_UNLOCK(fm_ops_lock); + parm->num = chl_cnt; + return ret; +} + + +fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm) +{ + fm_s32 ret = 0; + fm_s32 space_idx = 0x0002; + + FMR_ASSERT(fm_low_ops.bi.setfreq); + FMR_ASSERT(fm_low_ops.bi.rssiget); + FMR_ASSERT(fm_low_ops.bi.rampdown); + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (parm->freq < parm->lower || parm->freq > parm->upper) { + WCN_DBG(FM_ERR | MAIN, "seek start freq:%d out of range\n", parm->freq); + ret = -EPERM; + goto out; + } + + // tune to start freq + fm_low_ops.bi.rampdown(); + fm_low_ops.bi.setfreq(parm->freq); + + if (parm->space == 5) { + space_idx = 0x0001; + } else if (parm->space == 10) { + space_idx = 0x0002; + } else if (parm->space == 20) { + space_idx = 0x0004; + } + + fm_op_state_set(fm, FM_STA_SEEK); + if (fm_false == fm_low_ops.bi.seek(parm->lower, parm->upper, &(parm->freq), parm->dir, space_idx)) { + ret = -1; + goto out; + } + + // tune to new channel + fm_low_ops.bi.setfreq(parm->freq); + fm_low_ops.bi.rssiget(&parm->th); + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + + +fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.mute); + FMR_ASSERT(fm_low_ops.bi.rampdown); + FMR_ASSERT(fm_low_ops.bi.setfreq); + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + WCN_DBG(FM_DBG | MAIN, "%s\n", __func__); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + goto out; + } + + if (parm->freq < parm->lower || parm->freq > parm->upper) { + WCN_DBG(FM_ERR | MAIN, "tune freq:%d out of range\n", parm->freq); + ret = -EPERM; + goto out; + } + +// fm_low_ops.bi.mute(fm_true); + fm_low_ops.bi.rampdown(); + + if (fm_cur_freq_get() != parm->freq) { + fm_memset(fm->pstRDSData, 0, sizeof(rds_t)); + } + +#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM)) + //HILO side adjust if need + if (priv_adv.priv_tbl.hl_dese) { + if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret); + } + + //Frequency avoid adjust if need + if (priv_adv.priv_tbl.fa_dese) { + if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "FA %d\n", ret); + } + + //MCU clock adjust if need + if (priv_adv.priv_tbl.mcu_dese) { + if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); + } + + //GPS clock adjust if need + if (priv_adv.priv_tbl.gps_dese) { + if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); + } +#endif + fm_op_state_set(fm, FM_STA_TUNE); + WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq); + + if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) { + WCN_DBG(FM_ALT | MAIN, "FM tune failed\n"); + ret = -EPERM; + goto out; + } + +// fm_low_ops.bi.mute(fm_false); + fm_op_state_set(fm, FM_STA_PLAY); +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + + +fm_s32 fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size) +{ + fm_s32 ret = 0; + fm_s32 idx = 0; + + FMR_ASSERT(fm_low_ops.bi.cqi_get); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_true == scan_stop_flag) { + WCN_DBG(FM_NTC | MAIN, "scan flow aborted, do not get CQI\n"); + ret = -1; + goto out; + } + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + goto out; + } + + if (ch_num*sizeof(struct fm_cqi) > buf_size) { + ret = -EPERM; + goto out; + } + + fm_op_state_set(fm, FM_STA_SCAN); + + idx = 0; + WCN_DBG(FM_NTC | MAIN, "cqi num %d\n", ch_num); + + while (ch_num > 0) { + ret = fm_low_ops.bi.cqi_get(buf + 16 * sizeof(struct fm_cqi) * idx, buf_size - 16 * sizeof(struct fm_cqi) * idx); + + if (ret) { + goto out; + } + + ch_num -= 16; + idx++; + } + + fm_op_state_set(fm, FM_STA_STOP); + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + + +/* fm_is_dese_chan -- check if gived channel is a de-sense channel or not + * @pfm - fm driver global DS + * @freq - gived channel + * return value: 0, not a dese chan; 1, a dese chan; else error NO. + */ +fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq) +{ + fm_s32 ret = 0; + FMR_ASSERT(pfm); + if (fm_low_ops.bi.is_dese_chan) + { + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + ret = fm_low_ops.bi.is_dese_chan(freq); + FM_UNLOCK(fm_ops_lock); + } + + return ret; +} + + +/* fm_is_dese_chan -- check if gived channel is a de-sense channel or not + * @pfm - fm driver global DS + * @freq - gived channel + * return value: 0, not a dese chan; 1, a dese chan; else error NO. + */ +fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi) +{ + fm_s32 ret = 0; + FMR_ASSERT(pfm); + if (fm_low_ops.bi.desense_check) + { + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + ret = fm_low_ops.bi.desense_check(freq,rssi); + FM_UNLOCK(fm_ops_lock); + } + + return ret; +} +fm_s32 fm_dump_reg(void) +{ + fm_s32 ret = 0; + if (fm_low_ops.bi.dumpreg) + { + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + ret = fm_low_ops.bi.dumpreg(); + FM_UNLOCK(fm_ops_lock); + } + return ret; +} + +/* fm_get_hw_info -- hw info: chip id, ECO version, DSP ROM version, Patch version + * @pfm - fm driver global DS + * @freq - target buffer + * return value: 0, success; else error NO. + */ +fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req) +{ + fm_s32 ret = 0; + + FMR_ASSERT(req); + + //default value for all chips + req->chip_id = 0x000066FF; + req->eco_ver = 0x00000000; + req->rom_ver = 0x00000001; + req->patch_ver = 0x00000100; + req->reserve = 0x00000000; + + //get actual chip hw info + if (fm_low_ops.bi.hwinfo_get) { + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + ret = fm_low_ops.bi.hwinfo_get(req); + FM_UNLOCK(fm_ops_lock); + } + + return ret; +} + + +/* fm_get_i2s_info -- i2s info: on/off, master/slave, sample rate + * @pfm - fm driver global DS + * @freq - target buffer + * return value: 0, success; else error NO. + */ +fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req) +{ + FMR_ASSERT(req); + + if (fm_low_ops.bi.i2s_get) { + return fm_low_ops.bi.i2s_get(&req->status, &req->mode, &req->rate); + } else { + req->status = fm_i2s_inf.status; + req->mode = fm_i2s_inf.mode; + req->rate = fm_i2s_inf.rate; + + return 0; + } +} + + +fm_s32 fm_hwscan_stop(struct fm *fm) +{ + fm_s32 ret = 0; + + if ((FM_STA_SCAN != fm_op_state_get(fm))&&(FM_STA_SEEK!=fm_op_state_get(fm))) + { + WCN_DBG(FM_WAR | MAIN, "fm isn't on scan, no need stop\n"); + return ret; + } + + FMR_ASSERT(fm_low_ops.bi.scanstop); + + fm_low_ops.bi.scanstop(); + fm_low_ops.bi.seekstop(); + scan_stop_flag = fm_true; + WCN_DBG(FM_DBG | MAIN, "fm will stop scan\n"); + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + fm_low_ops.bi.rampdown(); + fm_low_ops.bi.setfreq(fm_cur_freq_get()); + + FM_UNLOCK(fm_ops_lock); + + return ret; +} + +/* fm_ana_switch -- switch antenna to long/short + * @fm - fm driver main data structure + * @antenna - 0, long; 1, short + * If success, return 0; else error code + */ +fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.anaswitch); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + WCN_DBG(FM_DBG | MAIN, "Switching ana to %s\n", antenna ? "short" : "long"); + fm->ana_type = antenna; + ret = fm_low_ops.bi.anaswitch(antenna); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "Switch ana Failed\n"); + } else { + WCN_DBG(FM_DBG | MAIN, "Switch ana OK!\n"); + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +//volume?[0~15] +fm_s32 fm_setvol(struct fm *fm, fm_u32 vol) +{ + fm_u8 tmp_vol; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + return -EPERM; + } + FMR_ASSERT(fm_low_ops.bi.volset); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + tmp_vol = (vol > 15) ? 15 : vol; + fm_low_ops.bi.volset(tmp_vol); + fm->vol = (fm_s32)tmp_vol; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol) +{ + fm_u8 tmp_vol; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + return -EPERM; + } + FMR_ASSERT(fm_low_ops.bi.volget); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + fm_low_ops.bi.volget(&tmp_vol); + *vol = (fm_u32)tmp_vol; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +fm_s32 fm_mute(struct fm *fm, fm_u32 bmute) +{ + fm_s32 ret = 0; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + return ret; + } + FMR_ASSERT(fm_low_ops.bi.mute); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (bmute) { + ret = fm_low_ops.bi.mute(fm_true); + fm->mute = fm_true; + } else { + ret = fm_low_ops.bi.mute(fm_false); + fm->mute = fm_false; + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi) +{ + fm_s32 ret = 0; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + return ret; + } + FMR_ASSERT(fm_low_ops.bi.rssiget); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.rssiget(rssi); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.read); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.read(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.write); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.write(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid) +{ + FMR_ASSERT(chipid); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + *chipid = fm->chip_id; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.msget); + FMR_ASSERT(ms); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_low_ops.bi.msget(ms) == fm_false) { + ret = -FM_EPARA; + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* + * Force set to stero/mono mode + * @MonoStereo -- 0, auto; 1, mono + * If success, return 0; else error code + */ +fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.msset); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.msset(ms); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.pamdget); + FMR_ASSERT(pamd); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_low_ops.bi.pamdget(pamd) == fm_false) { + ret = -FM_EPARA; + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.caparray_get); + FMR_ASSERT(ca); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.caparray_get(ca); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.em); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (fm_false == fm_low_ops.bi.em(group, item, val)) { + ret = -FM_EPARA; + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_tx); + FMR_ASSERT(fm_low_ops.ri.rds_tx_enable); + + if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) { + parm->err = FM_BADSTATUS; + ret = -FM_EPARA; + goto out; + } + if(parm->other_rds_cnt > 29) + { + parm->err = FM_EPARM; + WCN_DBG(FM_ERR | MAIN,"other_rds_cnt=%d\n",parm->other_rds_cnt); + ret = -FM_EPARA; + goto out; + } + + ret = fm_low_ops.ri.rds_tx_enable(); + if(ret){ + WCN_DBG(FM_ERR | MAIN,"Rds_Tx_Enable failed!\n"); + goto out; + } + fm->rdstx_on = fm_true; + ret = fm_low_ops.ri.rds_tx(parm->pi, parm->ps, parm->other_rds, parm->other_rds_cnt); + if(ret){ + WCN_DBG(FM_ERR | MAIN,"Rds_Tx failed!\n"); + goto out; + } +// fm_cxt->txcxt.rdsTxOn = true; +// fm_cxt->txcxt.pi = parm->pi; +// memcpy(fm_cxt->txcxt.ps, parm->ps,sizeof(parm->ps)); +// memcpy(fm_cxt->txcxt.other_rds, parm->other_rds,sizeof(parm->other_rds)); +// fm_cxt->txcxt.other_rds_cnt = parm->other_rds_cnt; +out: + return ret; +} + +fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_onoff); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + if (rdson_off) { + fm->rds_on = fm_true; + if (fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_true) == fm_false) { + WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDS_ONOFF faield\n"); + ret = -EPERM; + goto out; + } + + fm_enable_rds_BlerCheck(fm); + } else { + fm->rds_on = fm_false; + fm_disable_rds_BlerCheck(); + fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false); + } + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_gbc_get); + FMR_ASSERT(gbc); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + *gbc = fm_low_ops.ri.rds_gbc_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_bbc_get); + FMR_ASSERT(bbc); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + *bbc = fm_low_ops.ri.rds_bbc_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_bbr_get); + FMR_ASSERT(bbr); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + *bbr = (fm_u16)fm_low_ops.ri.rds_bbr_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_gc_get); + FMR_ASSERT(dst); + if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK); + + ret = fm_low_ops.ri.rds_gc_get(dst, fm->pstRDSData); + + FM_UNLOCK(fm_rds_cnt); + return ret; +} + +fm_s32 fm_rds_group_cnt_reset(struct fm *fm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_gc_reset); + if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK); + + ret = fm_low_ops.ri.rds_gc_reset(fm->pstRDSData); + + FM_UNLOCK(fm_rds_cnt); + return ret; +} + +fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_log_get); + FMR_ASSERT(dst); + FMR_ASSERT(dst_len); + if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.ri.rds_log_get(dst, dst_len); + + FM_UNLOCK(fm_read_lock); + return ret; +} + +fm_s32 fm_rds_block_cnt_reset(struct fm *fm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.ri.rds_bc_reset); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.ri.rds_bc_reset(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.i2s_set); + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + ret = fm_low_ops.bi.i2s_set(onoff, mode, sample); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* + * fm_tune_tx + */ +fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.tune_tx); + + if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) { + parm->err = FM_BADSTATUS; + return -EPERM; + } + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + WCN_DBG(FM_DBG | MAIN, "%s\n", __func__); + + fm_op_state_set(fm, FM_STA_TUNE); + WCN_DBG(FM_NTC | MAIN, "Tx tune to %d\n", parm->freq); +#if 0//ramp down tx will do in tx tune flow + while(0){ + if((ret = MT6620_RampDown_Tx())) + return ret; + } +#endif + //tune to desired channel + if (fm_true != fm_low_ops.bi.tune_tx(parm->freq)) + { + parm->err = FM_TUNE_FAILED; + WCN_DBG(FM_ALT | MAIN, "Tx tune failed\n"); + ret = -EPERM; + } + fm_op_state_set(fm, FM_STA_PLAY); + FM_UNLOCK(fm_ops_lock); + + return ret; +} + +/* + * fm_tune + */ +fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.mute); + FMR_ASSERT(fm_low_ops.bi.rampdown); + FMR_ASSERT(fm_low_ops.bi.setfreq); + + if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK); + + WCN_DBG(FM_DBG | MAIN, "%s\n", __func__); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + parm->err = FM_BADSTATUS; + ret = -EPERM; + goto out; + } + +// fm_low_ops.bi.mute(fm_true); + fm_low_ops.bi.rampdown(); + + if (fm_cur_freq_get() != parm->freq) { + fm_memset(fm->pstRDSData, 0, sizeof(rds_t)); + } + +#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM)) + //HILO side adjust if need + if (priv_adv.priv_tbl.hl_dese) { + if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret); + } + + //Frequency avoid adjust if need + if (priv_adv.priv_tbl.fa_dese) { + if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "FA %d\n", ret); + } + + //MCU clock adjust if need + if (priv_adv.priv_tbl.mcu_dese) { + if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); + } + + //GPS clock adjust if need + if (priv_adv.priv_tbl.gps_dese) { + if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) { + goto out; + } + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); + } +#endif + fm_op_state_set(fm, FM_STA_TUNE); + WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq); + + if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) { + parm->err = FM_TUNE_FAILED; + WCN_DBG(FM_ALT | MAIN, "FM tune failed\n"); + ret = -EPERM; + } + +// fm_low_ops.bi.mute(fm_false); + fm_op_state_set(fm, FM_STA_PLAY); +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} +//cqi log tool entry +fm_s32 fm_cqi_log(void) +{ + fm_s32 ret = 0; + fm_u16 freq; + FMR_ASSERT(fm_low_ops.bi.cqi_log); + freq = fm_cur_freq_get(); + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + if((freq != 10000) && (0xffffffff != g_dbg_level)) + { + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + ret = fm_low_ops.bi.cqi_log(8750,10800,2,5); + FM_UNLOCK(fm_ops_lock); + return ret; +} +/*fm soft mute tune function*/ +fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm_low_ops.bi.softmute_tune); + + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + { + parm->valid = fm_false; + ret = -EPERM; + goto out; + } + + // fm_low_ops.bi.mute(fm_true); + WCN_DBG(FM_NTC | MAIN, "+%s():[freq=%d]\n", __func__, parm->freq); + //fm_op_state_set(fm, FM_STA_TUNE); + + if (fm_false == fm_low_ops.bi.softmute_tune(parm->freq,&parm->rssi,&parm->valid)) + { + parm->valid = fm_false; + WCN_DBG(FM_ALT | MAIN, "sm tune failed\n"); + ret = -EPERM; + } + +// fm_low_ops.bi.mute(fm_false); +out: + WCN_DBG(FM_NTC | MAIN, "-%s()\n", __func__); + FM_UNLOCK(fm_ops_lock); + + return ret; +} +fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag) +{ + fm_s32 ret = 0; + FMR_ASSERT(fm_low_ops.bi.fm_via_bt); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + { + return -EPERM; + } + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + + ret = fm_low_ops.bi.fm_via_bt(flag); + if(ret) + { + WCN_DBG(FM_ALT | MAIN,"%s(),failed!\n", __func__); + } + else + { + fm->via_bt = flag; + } + WCN_DBG(FM_NTC | MAIN,"%s(),[ret=%d]!\n", __func__, ret); + FM_UNLOCK(fm_ops_lock); + return ret; +} +fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support) +{ + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + if(fm_low_ops.bi.tx_support) + { + fm_low_ops.bi.tx_support(support); + } + else + { + *support=0; + } + WCN_DBG(FM_NTC | MAIN,"%s(),[%d]!\n", __func__, *support); + FM_UNLOCK(fm_ops_lock); + return 0; +} +fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support) +{ + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + if(fm_low_ops.ri.rdstx_support) + { + fm_low_ops.ri.rdstx_support(support); + } + else + { + *support=0; + } + WCN_DBG(FM_NTC | MAIN,"support=[%d]!\n", *support); + FM_UNLOCK(fm_ops_lock); + return 0; +} +fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support) +{ + if (FM_LOCK(fm_ops_lock)) + return (-FM_ELOCK); + if(fm->rdstx_on) + { + *support=1; + } + else + { + *support=0; + } + WCN_DBG(FM_NTC | MAIN,"rds tx enable=[%d]!\n", *support); + FM_UNLOCK(fm_ops_lock); + return 0; +} + +static void fm_timer_func(unsigned long data) +{ + struct fm *fm = g_fm_struct; + + if (FM_LOCK(fm_timer_lock)) return; + + if (fm_timer_sys->update(fm_timer_sys)) { + WCN_DBG(FM_NTC | MAIN, "timer skip\n"); + goto out; //fm timer is stoped before timeout + } + + if (fm != NULL) { + WCN_DBG(FM_NTC | MAIN, "timer:rds_wk\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rds_wk); + } + +out: + FM_UNLOCK(fm_timer_lock); +} + + +static void fmtx_timer_func(unsigned long data) +{ + struct fm *fm = g_fm_struct; + fm_s32 vco_cycle = 1; + + if (FM_LOCK(fm_timer_lock)) return; + + fm_timer_sys->count++; + if (fm != NULL) + { + //schedule tx pwr ctrl work if need + if(fm->txpwrctl < 1) + { + WCN_DBG(FM_WAR | MAIN,"tx power ctl time err\n"); + fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_MIN; + } + if((fm_timer_sys->tx_pwr_ctrl_en == FM_TX_PWR_CTRL_ENABLE) && (fm_timer_sys->count%fm->txpwrctl == 0)) + { + WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_power_ctrl_work\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_power_ctrl_work); + } + /* + //schedule tx RTC ctrl work if need + if((timer->tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE)&& (timer->count%FM_TX_RTC_CTRL_INTERVAL == 0)){ + FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies)); + queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); + }*/ + //schedule tx desense with wifi/bt work if need + if(fm->vcooff < 1) + { + WCN_DBG(FM_WAR | MAIN,"tx vco tracking time err\n"); + fm->vcooff = FM_TX_VCO_OFF_MIN; + } + vco_cycle = fm->vcooff + fm->vcoon/1000; + if((fm_timer_sys->tx_desense_en == FM_TX_DESENSE_ENABLE) && (fm_timer_sys->count%vco_cycle == 0)) + { + WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_desense_wifi_work\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_desense_wifi_work); + } + } + if (fm_timer_sys->update(fm_timer_sys)) { + WCN_DBG(FM_NTC | MAIN, "timer skip\n"); + goto out; //fm timer is stoped before timeout + } + +out: + FM_UNLOCK(fm_timer_lock); +} + +static void fm_tx_power_ctrl_worker_func(unsigned long data) +{ + fm_s32 ctrl = 0,ret=0; + struct fm *fm = g_fm_struct; + + WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__); + + if(fm_low_ops.bi.tx_pwr_ctrl == NULL) + return; + if (FM_LOCK(fm_rxtx_lock)) return; + + if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){ + WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n"); + goto out; + } + + ctrl = fm->tx_pwr; + WCN_DBG(FM_NTC | MAIN,"tx pwr %ddb\n", ctrl); + ret = fm_low_ops.bi.tx_pwr_ctrl(fm_cur_freq_get(), &ctrl); + if(ret) + { + WCN_DBG(FM_ERR | MAIN,"tx_pwr_ctrl fail\n"); + } + +out: + FM_UNLOCK(fm_rxtx_lock); + WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__); + return; +} +static void fm_tx_rtc_ctrl_worker_func(unsigned long data) +{ + fm_s32 ret = 0; + fm_s32 ctrl = 0; + struct fm_gps_rtc_info rtcInfo; + //struct timeval curTime; + //struct fm *fm = (struct fm*)fm_cb; + unsigned long curTime = 0; + + WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__); + + if(FM_LOCK(fm_rtc_mutex)) return; + + if(gps_rtc_info.flag == FM_GPS_RTC_INFO_NEW){ + memcpy(&rtcInfo, &gps_rtc_info, sizeof(struct fm_gps_rtc_info)); + gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD; + FM_UNLOCK(fm_rtc_mutex); + }else{ + WCN_DBG(FM_NTC | MAIN,"there's no new rtc drift info\n"); + FM_UNLOCK(fm_rtc_mutex); + goto out; + } + + if(rtcInfo.age > rtcInfo.ageThd){ + WCN_DBG(FM_WAR | MAIN,"age over it's threshlod\n"); + goto out; + } + if((rtcInfo.drift <= rtcInfo.driftThd) && (rtcInfo.drift >= -rtcInfo.driftThd)){ + WCN_DBG(FM_WAR | MAIN,"drift over it's MIN threshlod\n"); + goto out; + } + + if(rtcInfo.drift > FM_GPS_RTC_DRIFT_MAX){ + WCN_DBG(FM_WAR | MAIN,"drift over it's +MAX threshlod\n"); + rtcInfo.drift = FM_GPS_RTC_DRIFT_MAX; + goto out; + }else if(rtcInfo.drift < -FM_GPS_RTC_DRIFT_MAX){ + WCN_DBG(FM_WAR | MAIN,"drift over it's -MAX threshlod\n"); + rtcInfo.drift = -FM_GPS_RTC_DRIFT_MAX; + goto out; + } + /* + //get current time + do_gettimeofday(&curTime); + if((curTime.tv_sec - rtcInfo.tv.tv_sec) > rtcInfo.tvThd.tv_sec){ + FM_LOG_WAR(D_MAIN,"time diff over it's threshlod\n"); + goto out; + }*/ + curTime = jiffies; + if(((long)curTime - (long)rtcInfo.stamp)/HZ > rtcInfo.tvThd.tv_sec){ + WCN_DBG(FM_WAR | MAIN,"time diff over it's threshlod\n"); + goto out; + } + if(fm_low_ops.bi.rtc_drift_ctrl != NULL) + { + ctrl = rtcInfo.drift; + WCN_DBG(FM_NTC | MAIN,"RTC_drift_ctrl[0x%08x]\n", ctrl); + if((ret = fm_low_ops.bi.rtc_drift_ctrl(fm_cur_freq_get(), &ctrl))) + goto out; + } +out: + WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__); + return; +} + +static void fm_tx_desense_wifi_worker_func(unsigned long data) +{ + fm_s32 ret = 0; + fm_s32 ctrl = 0; + struct fm *fm = g_fm_struct; + + WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__); + + if (FM_LOCK(fm_rxtx_lock)) return; + + if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){ + WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n"); + goto out; + } + + fm_tx_rtc_ctrl_worker_func(0); + + ctrl = fm->vcoon; + if(fm_low_ops.bi.tx_desense_wifi) + { + WCN_DBG(FM_NTC | MAIN,"tx_desense_wifi[%d]\n", ctrl); + ret = fm_low_ops.bi.tx_desense_wifi(fm_cur_freq_get(), &ctrl); + if(ret) + { + WCN_DBG(FM_ERR | MAIN,"tx_desense_wifi fail\n"); + } + } +out: + FM_UNLOCK(fm_rxtx_lock); + WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__); + return; +} + +/* +************************************************************************************ +Function: fm_get_gps_rtc_info() + +Description: get GPS RTC drift info, and this function should not block + +Date: 2011/04/10 + +Return Value: success:0, failed: error coe +************************************************************************************ +*/ +fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src) +{ + fm_s32 ret = 0; +// fm_s32 retry_cnt = 0; + struct fm_gps_rtc_info *dst=&gps_rtc_info; + + FMR_ASSERT(src); + FMR_ASSERT(dst); + + if(src->retryCnt > 0){ + dst->retryCnt = src->retryCnt; + WCN_DBG(FM_NTC | MAIN,"%s, new [retryCnt=%d]\n", __func__, dst->retryCnt); + } + if(src->ageThd > 0){ + dst->ageThd = src->ageThd; + WCN_DBG(FM_NTC | MAIN,"%s, new [ageThd=%d]\n", __func__, dst->ageThd); + } + if(src->driftThd > 0){ + dst->driftThd = src->driftThd; + WCN_DBG(FM_NTC | MAIN,"%s, new [driftThd=%d]\n", __func__, dst->driftThd); + } + if(src->tvThd.tv_sec > 0){ + dst->tvThd.tv_sec = src->tvThd.tv_sec; + WCN_DBG(FM_NTC | MAIN,"%s, new [tvThd=%d]\n", __func__, (fm_s32)dst->tvThd.tv_sec); + } + ret = fm_rtc_mutex->trylock(fm_rtc_mutex,dst->retryCnt); + if(ret) + { + goto out; + } + dst->age = src->age; + dst->drift = src->drift; + dst->stamp = jiffies; //get curren time stamp + dst->flag = FM_GPS_RTC_INFO_NEW; + + FM_UNLOCK(fm_rtc_mutex); + + /* + //send event to info fm_tx_rtc_ctrl_work + if(timer_sys.tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE){ + FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies)); + queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); + } + */ + +out: + return ret; +} + +static void fm_enable_rds_BlerCheck(struct fm *fm) +{ + if (FM_LOCK(fm_timer_lock)) return; + fm_timer_sys->start(fm_timer_sys); + FM_UNLOCK(fm_timer_lock); +} + +static void fm_disable_rds_BlerCheck(void) +{ + if (FM_LOCK(fm_timer_lock)) return; + fm_timer_sys->stop(fm_timer_sys); + FM_UNLOCK(fm_timer_lock); +} + +void fm_rds_reset_work_func(unsigned long data) +{ + fm_s32 ret = 0; + + if (!fm_low_ops.ri.rds_blercheck) { + return; + } + if (FM_LOCK(fm_rxtx_lock)) return; + + if (FM_LOCK(fm_rds_cnt)) return; + ret = fm_low_ops.ri.rds_blercheck(g_fm_struct->pstRDSData); + + WCN_DBG(FM_NTC | MAIN, "Addr_Cnt=%x\n",g_fm_struct->pstRDSData->AF_Data.Addr_Cnt); + if(g_fm_struct->pstRDSData->AF_Data.Addr_Cnt == 0xFF)//check af list get,can't use event==af_list because event will clear after read rds every time + { + g_fm_struct->pstRDSData->event_status |= RDS_EVENT_AF; + } + if (!ret && g_fm_struct->pstRDSData->event_status) + { + FM_EVENT_SEND(g_fm_struct->rds_event, FM_RDS_DATA_READY); + } + WCN_DBG(FM_NTC | MAIN, "rds event check=%x\n",g_fm_struct->pstRDSData->event_status); + FM_UNLOCK(fm_rds_cnt); + FM_UNLOCK(fm_rxtx_lock); +} + + +void fm_subsys_reset_work_func(unsigned long data) +{ + g_dbg_level = 0xffffffff; + if (FM_LOCK(fm_ops_lock)) return; + + fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_START); + + if (g_fm_struct->chipon == fm_false) + { + WCN_DBG(FM_ALT | MAIN, "no need do recover\n"); + goto out; + } + // subsystem power off + fm_low_ops.bi.pwroff(0); + + // prepare to reset + + // wait 3s + fm_low_ops.bi.msdelay(2000); + + // subsystem power on + fm_low_ops.bi.pwron(0); + + // recover context + if (g_fm_struct->chipon == fm_false) { + fm_low_ops.bi.pwroff(0); + WCN_DBG(FM_ALT | MAIN, "no need do recover\n"); + goto out; + } + + if (FM_PWR_RX_ON == fm_pwr_state_get(g_fm_struct)) { + fm_low_ops.bi.pwrupseq(&g_fm_struct->chip_id, &g_fm_struct->device_id); + } else { + WCN_DBG(FM_ALT | MAIN, "no need do re-powerup\n"); + goto out; + } + + fm_low_ops.bi.anaswitch(g_fm_struct->ana_type); + + fm_low_ops.bi.setfreq(fm_cur_freq_get()); + + fm_low_ops.bi.volset((fm_u8)g_fm_struct->vol); + + fm_low_ops.bi.mute(g_fm_struct->mute); + + fm_low_ops.ri.rds_onoff(g_fm_struct->pstRDSData, g_fm_struct->rds_on); + + WCN_DBG(FM_ALT | MAIN, "recover done\n"); + +out: + fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_END); + fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_OFF); + + FM_UNLOCK(fm_ops_lock); + g_dbg_level = 0xfffffff5; +} + +static void fm_eint_handler(void) +{ + struct fm *fm = g_fm_struct; + WCN_DBG(FM_DBG | MAIN, "intr occur, ticks:%d\n", jiffies_to_msecs(jiffies)); + + if (fm != NULL) { + fm->eint_wkthd->add_work(fm->eint_wkthd, fm->eint_wk); + } +} + +static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size) +{ + struct fm *fm = g_fm_struct;//(struct fm *)work->data; + rds_t *pstRDSData = fm->pstRDSData; + + if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK); + //parsing RDS data + fm_low_ops.ri.rds_parser(pstRDSData, rds_raw, rds_size, fm_cur_freq_get); + FM_UNLOCK(fm_read_lock); + + if ((pstRDSData->event_status != 0x0000) && (pstRDSData->event_status != RDS_EVENT_AF_LIST)) { + WCN_DBG(FM_NTC | MAIN, "Notify user to read, [event:%04x]\n", pstRDSData->event_status); + FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY); + } + + return 0; +} + +static void fm_eint_work_func(unsigned long data) +{ + fm_event_parser(fm_rds_parser); + //re-enable eint if need + fm_enable_eint(); +} + +static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops) +{ + FMR_ASSERT(ops); + + ops->cb.cur_freq_get = fm_cur_freq_get; + ops->cb.cur_freq_set = fm_cur_freq_set; + return 0; +} + +static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops) +{ + FMR_ASSERT(ops); + + fm_memset(&ops->cb, 0, sizeof(struct fm_callback)); + return 0; +} + + +static fm_s32 fm_para_init(struct fm *fmp) +{ + FMR_ASSERT(fmp); + + fmp->band = FM_BAND_SPECIAL; + fmp->min_freq = FM_RX_BAND_FREQ_L; + fmp->max_freq = FM_RX_BAND_FREQ_H; + fmp->cur_freq = 0; + + return 0; +} + +fm_s32 fm_cust_config_setup(fm_s8 * filename) +{ + fm_s32 ret; +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#ifdef MT6628_FM + ret = MT6628fm_cust_config_setup(filename); + if(ret < 0) + { + WCN_DBG(FM_ERR | MAIN, "MT6628fm_cust_config_setup failed\n"); + } +#endif +#ifdef MT6620_FM + ret = MT6620fm_cust_config_setup(filename); + if(ret < 0) + { + WCN_DBG(FM_ERR | MAIN, "MT6620fm_cust_config_setup failed\n"); + } +#endif +#else + fm_cust_config(filename); + if(ret < 0) + { + WCN_DBG(FM_ERR | MAIN, "fm_cust_config failed\n"); + } +#endif + return ret; +} + +struct fm* fm_dev_init(fm_u32 arg) +{ + fm_s32 ret = 0; + struct fm *fm = NULL; + +// if (!fm_low_ops.ri.rds_bci_get) +// return NULL; + +// if (!fm_low_ops.bi.chipid_get) +// return NULL; + + //alloc fm main data structure + if (!(fm = fm_zalloc(sizeof(struct fm)))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } + + fm->ref = 0; + fm->chipon = fm_false; + fm_pwr_state_set(fm, FM_PWR_OFF); +// fm->chip_id = fm_low_ops.bi.chipid_get(); + //FM Tx + fm->vcoon = FM_TX_VCO_ON_DEFAULT; + fm->vcooff = FM_TX_VCO_OFF_DEFAULT; + fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_DEFAULT; + fm->tx_pwr = FM_TX_PWR_LEVEL_MAX; + gps_rtc_info.err = 0; + gps_rtc_info.age = 0; + gps_rtc_info.drift = 0; + gps_rtc_info.tv.tv_sec = 0; + gps_rtc_info.tv.tv_usec = 0; + gps_rtc_info.ageThd = FM_GPS_RTC_AGE_TH; + gps_rtc_info.driftThd = FM_GPS_RTC_DRIFT_TH; + gps_rtc_info.tvThd.tv_sec = FM_GPS_RTC_TIME_DIFF_TH; + gps_rtc_info.retryCnt = FM_GPS_RTC_RETRY_CNT; + gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD; + + if (!(fm->rds_event = fm_flag_event_create("fm_rds_event"))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS event\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } + + fm_flag_event_get(fm->rds_event); + + //alloc fm rds data structure + if (!(fm->pstRDSData = fm_zalloc(sizeof(rds_t)))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } + + g_fm_struct = fm; + + fm->timer_wkthd = fm_workthread_create("fm_timer_wq"); + + if (!fm->timer_wkthd) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_timer_wq\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } + + fm_workthread_get(fm->timer_wkthd); + + fm->eint_wkthd = fm_workthread_create("fm_eint_wq"); + + if (!fm->eint_wkthd) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_eint_wq\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } + + fm_workthread_get(fm->eint_wkthd); + + fm->eint_wk = fm_work_create("fm_eint_work"); + + if (!fm->eint_wk) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for eint_wk\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->eint_wk); + fm->eint_wk->init(fm->eint_wk, fm_eint_work_func, (unsigned long)fm); + } + + // create reset work + fm->rst_wk = fm_work_create("fm_rst_work"); + + if (!fm->rst_wk) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rst_wk\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->rst_wk); + fm->rst_wk->init(fm->rst_wk, fm_subsys_reset_work_func, (unsigned long)fm); + } + + fm->rds_wk = fm_work_create("fm_rds_work"); + if (!fm->rds_wk) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rds_wk\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->rds_wk); + fm->rds_wk->init(fm->rds_wk, fm_rds_reset_work_func, (unsigned long)fm); + } + + fm->fm_tx_power_ctrl_work = fm_work_create("tx_pwr_ctl_work"); + if (!fm->fm_tx_power_ctrl_work) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_pwr_ctl_work\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->fm_tx_power_ctrl_work); + fm->fm_tx_power_ctrl_work->init(fm->fm_tx_power_ctrl_work, fm_tx_power_ctrl_worker_func, (unsigned long)fm); + } + + fm->fm_tx_desense_wifi_work = fm_work_create("tx_desen_wifi_work"); + if (!fm->fm_tx_desense_wifi_work) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_desen_wifi_work\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->fm_tx_desense_wifi_work); + fm->fm_tx_desense_wifi_work->init(fm->fm_tx_desense_wifi_work, fm_tx_desense_wifi_worker_func, (unsigned long)fm); + } + + //fm timer was created in fm_env_setp() +// fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0); +// fm_timer_sys->start(fm_timer_sys); + + //init customer config parameter + fm_cust_config_setup(NULL); + + fm_para_init(fm); + + return g_fm_struct; + +ERR_EXIT: + + if (fm->eint_wkthd) { + ret = fm_workthread_put(fm->eint_wkthd); + + if (!ret) + fm->eint_wkthd = NULL; + } + + if (fm->timer_wkthd) { + ret = fm_workthread_put(fm->timer_wkthd); + + if (!ret) + fm->timer_wkthd = NULL; + } + + if (fm->eint_wk) { + ret = fm_work_put(fm->eint_wk); + + if (!ret) + fm->eint_wk = NULL; + } + + if (fm->rds_wk) { + ret = fm_work_put(fm->rds_wk); + + if (!ret) + fm->rds_wk = NULL; + } + + if (fm->rst_wk) { + ret = fm_work_put(fm->rst_wk); + + if (!ret) + fm->rst_wk = NULL; + } + + if (fm->fm_tx_desense_wifi_work) { + ret = fm_work_put(fm->fm_tx_desense_wifi_work); + + if (!ret) + fm->fm_tx_desense_wifi_work = NULL; + } + + if (fm->fm_tx_power_ctrl_work) { + ret = fm_work_put(fm->fm_tx_power_ctrl_work); + + if (!ret) + fm->fm_tx_power_ctrl_work = NULL; + } + + if (fm->pstRDSData) { + fm_free(fm->pstRDSData); + fm->pstRDSData = NULL; + } + + fm_free(fm); + g_fm_struct = NULL; + return NULL; +} + +fm_s32 fm_dev_destroy(struct fm *fm) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_DBG | MAIN, "%s\n", __func__); + + fm_timer_sys->stop(fm_timer_sys); + + if (fm->eint_wkthd) { + ret = fm_workthread_put(fm->eint_wkthd); + + if (!ret) + fm->eint_wkthd = NULL; + } + + if (fm->timer_wkthd) { + ret = fm_workthread_put(fm->timer_wkthd); + + if (!ret) + fm->timer_wkthd = NULL; + } + + if (fm->eint_wk) { + ret = fm_work_put(fm->eint_wk); + + if (!ret) + fm->eint_wk = NULL; + } + + if (fm->rds_wk) { + ret = fm_work_put(fm->rds_wk); + + if (!ret) + fm->rds_wk = NULL; + } + + if (fm->rst_wk) { + ret = fm_work_put(fm->rst_wk); + + if (!ret) + fm->rst_wk = NULL; + } + + if (fm->pstRDSData) { + fm_free(fm->pstRDSData); + fm->pstRDSData = NULL; + } + + if (fm->pstRDSData) { + fm_free(fm->pstRDSData); + fm->pstRDSData = NULL; + } + + fm_flag_event_put(fm->rds_event); + + // free all memory + if (fm) { + fm_free(fm); + fm = NULL; + g_fm_struct = NULL; + } + + return ret; +} + +fm_s32 fm_env_setup(void) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#ifdef MT6620_FM + //register call back functions + ret = fm_callback_register(&MT6620fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n"); + //get low level functions + ret = MT6620fm_low_ops_register(&MT6620fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n"); + //get rds level functions + ret = MT6620fm_rds_ops_register(&MT6620fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n"); +#endif +#ifdef MT6628_FM + //register call back functions + ret = fm_callback_register(&MT6628fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n"); + //get low level functions + ret = MT6628fm_low_ops_register(&MT6628fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n"); + //get rds level functions + ret = MT6628fm_rds_ops_register(&MT6628fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n"); +#endif +#else + //register call back functions + ret = fm_callback_register(&fm_low_ops); + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n"); + //get low level functions + ret = fm_low_ops_register(&fm_low_ops); + + if (ret) { + return ret; + } + + WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n"); + //get rds level functions + ret = fm_rds_ops_register(&fm_low_ops); + + if (ret) { + return ret; + } + WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n"); +#endif + + fm_ops_lock = fm_lock_create("ops_lock"); + + if (!fm_ops_lock) { + return -1; + } + + fm_read_lock = fm_lock_create("rds_read"); + + if (!fm_read_lock) { + return -1; + } + + fm_rds_cnt = fm_lock_create("rds_cnt"); + + if (!fm_rds_cnt) { + return -1; + } + + fm_timer_lock = fm_spin_lock_create("timer_lock"); + + if (!fm_timer_lock) { + return -1; + } + fm_rxtx_lock = fm_lock_create("rxtx_lock"); + if (!fm_rxtx_lock) { + return -1; + } + fm_rtc_mutex = fm_lock_create("rxtx_lock"); + if (!fm_rxtx_lock) { + return -1; + } + + fm_lock_get(fm_ops_lock); + fm_lock_get(fm_read_lock); + fm_lock_get(fm_rds_cnt); + fm_spin_lock_get(fm_timer_lock); + fm_lock_get(fm_rxtx_lock); + WCN_DBG(FM_NTC | MAIN, "4. fm locks created\n"); + + fm_timer_sys = fm_timer_create("fm_sys_timer"); + + if (!fm_timer_sys) { + return -1; + } + + fm_timer_get(fm_timer_sys); + WCN_DBG(FM_NTC | MAIN, "5. fm timer created\n"); + + ret = fm_link_setup((void*)fm_wholechip_rst_cb); + + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm link setup Failed\n"); + return -1; + } + + return ret; +} + +fm_s32 fm_env_destroy(void) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + fm_link_release(); + +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#if defined(MT6620_FM) + //register call back functions + ret = fm_callback_unregister(&MT6620fm_low_ops); + + if (ret) { + return -1; + } + //put low level functions + ret = MT6620fm_low_ops_unregister(&MT6620fm_low_ops); + + if (ret) { + return -1; + } + + //put rds func + ret = MT6620fm_rds_ops_unregister(&MT6620fm_low_ops); + + if (ret) { + return -1; + } +#endif +#if defined(MT6628_FM) + //register call back functions + ret = fm_callback_unregister(&MT6628fm_low_ops); + + if (ret) { + return -1; + } + //put low level functions + ret = MT6628fm_low_ops_unregister(&MT6628fm_low_ops); + + if (ret) { + return -1; + } + + //put rds func + ret = MT6628fm_rds_ops_unregister(&MT6628fm_low_ops); + + if (ret) { + return -1; + } +#endif +#else + //register call back functions + ret = fm_callback_unregister(&fm_low_ops); + + if (ret) { + return -1; + } + //put low level functions + ret = fm_low_ops_unregister(&fm_low_ops); + + if (ret) { + return -1; + } + + //put rds func + ret = fm_rds_ops_unregister(&fm_low_ops); + + if (ret) { + return -1; + } +#endif + ret = fm_lock_put(fm_ops_lock); + + if (!ret) + fm_ops_lock = NULL; + + ret = fm_lock_put(fm_read_lock); + + if (!ret) + fm_read_lock = NULL; + + ret = fm_lock_put(fm_rds_cnt); + + if (!ret) + fm_rds_cnt = NULL; + ret = fm_spin_lock_put(fm_timer_lock); + + if (!ret) + fm_timer_lock = NULL; + + ret = fm_timer_put(fm_timer_sys); + + if (!ret) + fm_timer_sys = NULL; + + return ret; +} + +#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM)) +fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub) +{ + fm_s32 ret = 0; + //Basic functions. + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + FMR_ASSERT(pri); + FMR_ASSERT(pub); + + // functions provided by private module + priv_adv.priv_tbl.hl_dese = pri->priv_tbl.hl_dese; + priv_adv.priv_tbl.fa_dese = pri->priv_tbl.fa_dese; + priv_adv.priv_tbl.mcu_dese = pri->priv_tbl.mcu_dese; + priv_adv.priv_tbl.gps_dese = pri->priv_tbl.gps_dese; + priv_adv.priv_tbl.chan_para_get = pri->priv_tbl.chan_para_get; + priv_adv.priv_tbl.is_dese_chan = pri->priv_tbl.is_dese_chan; + priv_adv.state = INITED; + priv_adv.data = NULL; + + // for special chip(chip with DSP) use + fm_low_ops.cb.chan_para_get = priv_adv.priv_tbl.chan_para_get; + + // private module will use these functions + pub->pub_tbl.read = fm_low_ops.bi.read; + pub->pub_tbl.write = fm_low_ops.bi.write; + pub->pub_tbl.setbits = fm_low_ops.bi.setbits; + pub->pub_tbl.rampdown = fm_low_ops.bi.rampdown; + pub->pub_tbl.msdelay = fm_low_ops.bi.msdelay; + pub->pub_tbl.usdelay = fm_low_ops.bi.usdelay; + pub->pub_tbl.log = (fm_s32 (*)(const fm_s8 *arg1, ...))printk; + pub->state = INITED; + pub->data = NULL; + + return ret; +} + +fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub) +{ + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + //FMR_ASSERT(pri); + FMR_ASSERT(pub); + + fm_memset(&priv_adv, 0, sizeof(struct fm_priv)); + fm_low_ops.cb.chan_para_get = NULL; + fm_memset(pub, 0, sizeof(struct fm_pub)); + + return 0; +} +#endif + +/* + * GetChannelSpace - get the spcace of gived channel + * @freq - value in 760~1080 or 7600~10800 + * + * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0 + */ +fm_s32 fm_get_channel_space(fm_s32 freq) +{ + if ((freq >= 760) && (freq <= 1080)) { + return 0; + } else if ((freq >= 7600) && (freq <= 10800)) { + return 1; + } else { + return -1; + } +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_module.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_module.c new file mode 100755 index 000000000000..bea07e573146 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_module.c @@ -0,0 +1,1388 @@ +/* fm_module.c + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * FM Radio Driver -- main functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // udelay() + +#include "fm_config.h" +#include "fm_main.h" +#include "fm_ioctl.h" + +#define FM_PROC_FILE "fm" + +fm_u32 g_dbg_level = 0xfffffff5; // Debug level of FM + +//fm main data structure +static struct fm *g_fm = NULL; +//proc file entry +static struct proc_dir_entry *g_fm_proc = NULL; + +//char device interface +static fm_s32 fm_cdev_setup(struct fm *fm); +static fm_s32 fm_cdev_destroy(struct fm *fm); + +static long fm_ops_ioctl(struct file *filp, fm_u32 cmd, unsigned long arg); +static loff_t fm_ops_lseek(struct file *filp, loff_t off, fm_s32 whence); +static ssize_t fm_ops_read(struct file *filp, char *buf, size_t len, loff_t *off); +static fm_s32 fm_ops_open(struct inode *inode, struct file *filp); +static fm_s32 fm_ops_release(struct inode *inode, struct file *filp); +static fm_s32 fm_ops_flush(struct file *filp,fl_owner_t Id); +static struct file_operations fm_ops = { + .owner = THIS_MODULE, + .unlocked_ioctl = fm_ops_ioctl, + .llseek = fm_ops_lseek, + .read = fm_ops_read, + .open = fm_ops_open, + .release = fm_ops_release, + .flush = fm_ops_flush, +}; + +static fm_s32 fm_proc_read(char *page, char **start, off_t off, fm_s32 count, fm_s32 *eof, void *data); +static fm_s32 fm_proc_write(struct file *file, const char *buffer, unsigned long count, void *data); + + +static struct fm_scan_t parm = { + .sr_size = 0, + .sr.ch_rssi_buf = NULL, +}; + +static long fm_ops_ioctl(struct file *filp, fm_u32 cmd, unsigned long arg) +{ + fm_s32 ret = 0; + struct fm_platform *plat = container_of(filp->f_dentry->d_inode->i_cdev, struct fm_platform, cdev); + struct fm *fm = container_of(plat, struct fm, platform); + + WCN_DBG(FM_NTC | MAIN, "%s---pid(%d)---cmd(0x%08x)---arg(0x%08x)\n", current->comm, current->pid, cmd, (fm_u32)arg); + + if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) { + WCN_DBG(FM_ALT | MAIN, "FM subsys is resetting, retry later\n"); + ret = -FM_ESRST; + return ret; + } + + switch (cmd) { + case FM_IOCTL_POWERUP: { + struct fm_tune_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:0\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + ret = fm_powerup(fm, &parm); + if (ret < 0) goto out; + ret = fm_tune(fm, &parm); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:1\n"); + + break; + } + + case FM_IOCTL_POWERDOWN: { + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERDOWN:0\n"); + ret = fm_powerdown(fm); + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERDOWN:1\n"); + break; + } + + case FM_IOCTL_TUNE: { + struct fm_tune_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE:0\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + ret = fm_tune(fm, &parm); + if (ret < 0) { + goto out; + } + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE:1\n"); + break; + } + + case FM_IOCTL_SOFT_MUTE_TUNE: + { + struct fm_softmute_tune_t parm; + fm_cqi_log();//cqi log tool + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_SOFT_MUTE_TUNE......\n"); + if(copy_from_user(&parm, (void*)arg, sizeof(struct fm_softmute_tune_t))) + { + ret = -EFAULT; + goto out; + } + + ret = fm_soft_mute_tune(fm, &parm); + if (ret < 0) { + goto out; + } + + if(copy_to_user((void*)arg, &parm, sizeof(struct fm_softmute_tune_t))) + { + ret = -EFAULT; + goto out; + } + break; + } + case FM_IOCTL_SEEK: { + struct fm_seek_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK:0\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_seek_parm))) { + ret = -EFAULT; + goto out; + } + + ret = fm_seek(fm, &parm); + if (ret < 0) { + goto out; + } + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_seek_parm))) { + ret = -EFAULT; + goto out; + } + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK:1\n"); + break; + } + + case FM_IOCTL_SCAN: { + struct fm_scan_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN start\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_scan_parm))) { + WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_scan(fm, &parm); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_scan_parm))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN end\n"); + break; + } + + case FM_IOCTL_TUNE_NEW: { + struct fm_tune_t tune_tmp; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_NEW\n"); + + if (copy_from_user(&tune_tmp, (void*)arg, sizeof(struct fm_tune_t))) { + WCN_DBG(FM_ERR | MAIN, "tune new copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_tune_new(fm, &tune_tmp); + if (ret < 0) { + goto out; + } + + if (copy_to_user((void*)arg, &tune_tmp, sizeof(struct fm_tune_t))) { + WCN_DBG(FM_ERR | MAIN, "tune new copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_SEEK_NEW: { + struct fm_seek_t seek_tmp; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK_NEW\n"); + + if (copy_from_user(&seek_tmp, (void*)arg, sizeof(struct fm_seek_t))) { + WCN_DBG(FM_ERR | MAIN, "seek new copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_seek_new(fm, &seek_tmp); + if (ret < 0) { + goto out; + } + + if (copy_to_user((void*)arg, &seek_tmp, sizeof(struct fm_seek_t))) { + WCN_DBG(FM_ERR | MAIN, "seek new copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_SCAN_NEW: { + struct fm_scan_t tmp; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN_NEW\n"); + + if (copy_from_user(&tmp, (void*)arg, sizeof(struct fm_scan_t))) { + WCN_DBG(FM_ERR | MAIN, "copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + switch (tmp.cmd) { + case FM_SCAN_CMD_START: + if ((tmp.upper > 10800) || (tmp.lower < 7600) || (tmp.space < 5) || (tmp.space > 20)) { + WCN_DBG(FM_ERR | MAIN, "scan para error\n"); + ret = -EFAULT; + goto out; + } + parm.cmd = tmp.cmd; + parm.lower = tmp.lower; + parm.upper = tmp.upper; + parm.space = tmp.space; + + ret = fm_scan_new(fm, &parm); + if (ret < 0) { + goto out; + } + break; + + case FM_SCAN_CMD_GET_CH_RSSI: + if (parm.sr_size && parm.sr.ch_rssi_buf) { + if (copy_to_user(tmp.sr.ch_rssi_buf, parm.sr.ch_rssi_buf, parm.num * sizeof(struct fm_ch_rssi))) { + WCN_DBG(FM_ERR | MAIN, "scan copy_to_user err\n"); + ret = -EFAULT; + goto out; + } + } + break; + + default: + break; + } + + tmp.num = parm.num; + if (copy_to_user((void*)arg, &tmp, sizeof(struct fm_scan_t))) { + WCN_DBG(FM_ERR | MAIN, "copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_CQI_GET: { + struct fm_cqi_req cqi_req; + fm_s8 *buf = NULL; + fm_s32 tmp; + + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_CQI_GET\n"); + + if (copy_from_user(&cqi_req, (void*)arg, sizeof(struct fm_cqi_req))) { + WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n"); + ret = -EFAULT; + goto out; + } + + if ((cqi_req.ch_num*sizeof(struct fm_cqi) > cqi_req.buf_size) || !cqi_req.cqi_buf) { + ret = -FM_EPARA; + goto out; + } + + tmp = cqi_req.ch_num / 16 + ((cqi_req.ch_num % 16) ? 1 : 0); + tmp = tmp * 16 * sizeof(struct fm_cqi); + buf = fm_zalloc(tmp); + + if (!buf) { + ret = -FM_ENOMEM; + goto out; + } + + ret = fm_cqi_get(fm, cqi_req.ch_num, buf, tmp); + + if (ret) { + fm_free(buf); + WCN_DBG(FM_ALT | MAIN, "get cqi failed\n"); + goto out; + } + + if (copy_to_user((void*)cqi_req.cqi_buf, buf, cqi_req.ch_num*sizeof(struct fm_cqi))) { + fm_free(buf); + ret = -EFAULT; + goto out; + } + + fm_free(buf); + break; + } + + case FM_IOCTL_GET_HW_INFO: { + struct fm_hw_info info; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GET_HW_INFO\n"); + + ret = fm_get_hw_info(fm, &info); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "get hw info failed\n"); + goto out; + } + + if (copy_to_user((void*)arg, &info, sizeof(struct fm_hw_info))) { + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_GET_I2S_INFO: { + struct fm_i2s_info i2sinfo; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GET_I2S_INFO\n"); + + ret = fm_get_i2s_info(fm, &i2sinfo); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "get i2s info failed\n"); + goto out; + } + + if (copy_to_user((void*)arg, &i2sinfo, sizeof(struct fm_i2s_info))) { + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_SETVOL: { + fm_u32 vol; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SETVOL start\n"); + if (copy_from_user(&vol, (void*)arg, sizeof(fm_u32))) { + WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_setvol(fm, vol); + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SETVOL end:%d\n", vol); + break; + } + case FM_IOCTL_GETVOL: { + fm_u32 vol; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETVOL start\n"); + ret = fm_getvol(fm, &vol); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &vol, sizeof(fm_u32))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETVOL end=%d\n",vol); + break; + } + + case FM_IOCTL_MUTE: { + fm_u32 bmute; + + WCN_DBG(FM_NTC| MAIN, "FM_IOCTL_MUTE start\n"); + if (copy_from_user(&bmute, (void*)arg, sizeof(fm_u32))) { + ret = -EFAULT; + goto out; + } + + ret = fm_mute(fm, bmute); + WCN_DBG(FM_NTC| MAIN, "FM_IOCTL_MUTE end-%d\n", bmute); + break; + } + + case FM_IOCTL_GETRSSI: { + fm_s32 rssi = 0; + + ret = fm_getrssi(fm, &rssi); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &rssi, sizeof(fm_s32))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETRSSI:%d\n",rssi); + break; + } + + case FM_IOCTL_RW_REG: { + struct fm_ctl_parm parm_ctl; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_RW_REG\n"); + + if (copy_from_user(&parm_ctl, (void*)arg, sizeof(struct fm_ctl_parm))) { + ret = -EFAULT; + goto out; + } + + if (parm_ctl.rw_flag == 0) { + ret = fm_reg_write(fm, parm_ctl.addr, parm_ctl.val); + } else { + ret = fm_reg_read(fm, parm_ctl.addr, &parm_ctl.val); + } + if (ret < 0) goto out; + + if ((parm_ctl.rw_flag == 0x01) && (!ret)) { + if (copy_to_user((void*)arg, &parm_ctl, sizeof(struct fm_ctl_parm))) { + ret = -EFAULT; + goto out; + } + } + + break; + } + + case FM_IOCTL_GETCHIPID: { + fm_u16 chipid; + + ret = fm_chipid_get(fm, &chipid); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCHIPID:%04x\n", chipid); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &chipid, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETMONOSTERO: { + fm_u16 usStereoMono; + + ret = fm_monostereo_get(fm, &usStereoMono); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETMONOSTERO:%04x\n", usStereoMono); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &usStereoMono, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_SETMONOSTERO: { + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_SETMONOSTERO, %d\n", (fm_s32)arg); + ret = fm_monostereo_set(fm, (fm_s32)arg); + break; + } + + case FM_IOCTL_GETCURPAMD: { + fm_u16 PamdLevl; + + ret = fm_pamd_get(fm, &PamdLevl); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCURPAMD:%d\n", PamdLevl); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &PamdLevl, sizeof(fm_u16))) + ret = -EFAULT; + goto out; + + break; + } + + case FM_IOCTL_GETCAPARRAY: { + fm_s32 ca; + + ret = fm_caparray_get(fm, &ca); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCAPARRAY:%d\n", ca); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &ca, sizeof(fm_s32))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_EM_TEST: { + struct fm_em_parm parm_em; + + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_EM_TEST\n"); + + if (copy_from_user(&parm_em, (void*)arg, sizeof(struct fm_em_parm))) { + ret = -EFAULT; + goto out; + } + ret = fm_em_test(fm, parm_em.group_idx, parm_em.item_idx, parm_em.item_value); + break; + } + + case FM_IOCTL_RDS_SUPPORT: { + fm_s32 support = FM_RDS_ENABLE; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_SUPPORT\n"); + + if (copy_to_user((void*)arg, &support, sizeof(fm_s32))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_IS_FM_POWERED_UP: { + fm_u32 powerup; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_FM_POWERED_UP"); + + if (fm->chipon && fm_pwr_state_get(fm)) { + powerup = 1; + } else { + powerup = 0; + } + + if (copy_to_user((void*)arg, &powerup, sizeof(fm_u32))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_RDS_ONOFF: { + fm_u16 rdson_off = 0; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_ONOFF start\n"); + + if (copy_from_user(&rdson_off, (void*)arg, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + ret = fm_rds_onoff(fm, rdson_off); + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_ONOFF end:%d\n",rdson_off); + break; + } + + case FM_IOCTL_GETGOODBCNT: { + fm_u16 uGBLCNT = 0; + + ret = fm_rds_good_bc_get(fm, &uGBLCNT); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETGOODBCNT:%d\n", uGBLCNT); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &uGBLCNT, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETBADBNT: { + fm_u16 uBadBLCNT = 0; + + ret = fm_rds_bad_bc_get(fm, &uBadBLCNT); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETBADBNT:%d\n", uBadBLCNT); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &uBadBLCNT, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETBLERRATIO: { + fm_u16 uBlerRatio = 0; + + ret = fm_rds_bler_ratio_get(fm, &uBlerRatio); + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETBLERRATIO:%d\n", uBlerRatio); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &uBlerRatio, sizeof(fm_u16))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_ANA_SWITCH: { + fm_s32 antenna = -1; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_ANA_SWITCH\n"); + + if (copy_from_user(&antenna, (void*)arg, sizeof(fm_s32))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_ana_switch(fm, antenna); + break; + } + + case FM_IOCTL_RDS_GROUPCNT: { + struct rds_group_cnt_req_t gc_req; + WCN_DBG(FM_DBG | MAIN, "......FM_IOCTL_RDS_GROUPCNT......\n"); + + if (copy_from_user(&gc_req, (void*)arg, sizeof(struct rds_group_cnt_req_t))) { + WCN_DBG(FM_ALT | MAIN, "copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + //handle group counter request + switch (gc_req.op) { + case RDS_GROUP_CNT_READ: + ret = fm_rds_group_cnt_get(fm, &gc_req.gc); + break; + case RDS_GROUP_CNT_WRITE: + break; + case RDS_GROUP_CNT_RESET: + ret = fm_rds_group_cnt_reset(fm); + break; + default: + break; + } + + if (copy_to_user((void*)arg, &gc_req, sizeof(struct rds_group_cnt_req_t))) { + WCN_DBG(FM_ALT | MAIN, "copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_RDS_GET_LOG: { + struct rds_raw_t rds_log; + fm_s32 len; + WCN_DBG(FM_DBG | MAIN, "......FM_IOCTL_RDS_GET_LOG......\n"); + //fetch a record form RDS log buffer + ret = fm_rds_log_get(fm, (struct rds_rx_t*) & (rds_log.data), &len); + rds_log.dirty = TRUE; + rds_log.len = (len < sizeof(rds_log.data)) ? len : sizeof(rds_log.data); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &rds_log, rds_log.len + 2*sizeof(fm_s32))) { + WCN_DBG(FM_ALT | MAIN, "copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_RDS_BC_RST: { + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_RDS_BC_RST\n"); + ret = fm_rds_block_cnt_reset(fm); + break; + } + + case FM_IOCTL_I2S_SETTING: { + struct fm_i2s_setting i2s_cfg; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_I2S_SETTING\n"); + + if (copy_from_user(&i2s_cfg, (void*)arg, sizeof(struct fm_i2s_setting))) { + WCN_DBG(FM_ALT | MAIN, "i2s set, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_i2s_set(fm, i2s_cfg.onoff, i2s_cfg.mode, i2s_cfg.sample); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "Set i2s err\n"); + goto out; + } + + break; + } + + case FM_IOCTL_IS_DESE_CHAN: { + fm_s32 tmp; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_DESE_CHAN\n"); + + if (copy_from_user(&tmp, (void*)arg, sizeof(fm_s32))) { + WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + + tmp = fm_is_dese_chan(fm, (fm_u16)tmp); + + if (copy_to_user((void*)arg, &tmp, sizeof(fm_s32))) { + WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_to_user err\n"); + ret = -EFAULT; + goto out; + } + + break; + } + case FM_IOCTL_DESENSE_CHECK: + { + fm_desense_check_t tmp; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_DESE_CHAN\n"); + + if (copy_from_user(&tmp, (void*)arg, sizeof(fm_desense_check_t))) + { + WCN_DBG(FM_ALT | MAIN, "desene check, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + ret = fm_desense_check(fm, (fm_u16)tmp.freq,tmp.rssi); + + /*if (copy_to_user((void*)arg, &tmp, sizeof(fm_desense_check_t))) { + WCN_DBG(FM_ALT | MAIN, "desene check, copy_to_user err\n"); + ret = -EFAULT; + goto out; + }*/ + + break; + } + case FM_IOCTL_SCAN_GETRSSI: + { + /*struct fm_rssi_req *req; + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_SCAN_GETRSSI\n"); + if(!(req = fm_vmalloc(sizeof(struct fm_rssi_req)))) + { + WCN_DBG(FM_ALT | MAIN, "fm_vmalloc err\n"); + ret = -EFAULT; + goto out; + } + if(copy_from_user(req, (void*)arg, sizeof(struct fm_rssi_req))) + { + WCN_DBG(FM_ALT | MAIN, "copy_from_user err\n"); + ret = -EFAULT; + fm_vfree(req); + goto out; + } + ret = fm_get_rssi_after_scan(fm, req); + if(-ERR_FW_NORES == ret){ + WCN_DBG(FM_ALT | MAIN, "fm_get_rssi_after_scan err\n"); + } + if(copy_to_user((void*)arg, req, sizeof(struct fm_rssi_req))) + { + WCN_DBG(FM_ALT | MAIN, "copy_to_user err\n"); + ret = -EFAULT; + fm_vfree(req); + goto out; + } + */ + WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_SCAN_GETRSSI:not support\n"); + break; + } + + case FM_IOCTL_DUMP_REG: + { + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_DUMP_REG......\n"); + + ret = fm_dump_reg(); + if(ret) + { + WCN_DBG(FM_ALT | MAIN, "fm_dump_reg err\n"); + } + break; + } + case FM_IOCTL_GPS_RTC_DRIFT:{ + struct fm_gps_rtc_info rtc_info; + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_GPS_RTC_DRIFT......\n"); + + if (fm_false == fm->chipon){ + WCN_DBG(FM_ERR | MAIN,"ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + if(copy_from_user(&rtc_info, (void*)arg, sizeof(struct fm_gps_rtc_info))){ + WCN_DBG(FM_ERR | MAIN,"copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_get_gps_rtc_info(&rtc_info); + if(ret){ + WCN_DBG(FM_ERR | MAIN,"fm_get_gps_rtc_info error\n"); + goto out; + } + break; + } + case FM_IOCTL_OVER_BT_ENABLE: + { + fm_s32 fm_via_bt = -1; + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_OVER_BT_ENABLE......\n"); + + if(copy_from_user(&fm_via_bt, (void*)arg, sizeof(int32_t))){ + WCN_DBG(FM_ERR | MAIN,"copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_over_bt(fm, fm_via_bt); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "fm_over_bt err\n"); + } + break; + } + + /***************************FM Tx function************************************/ + case FM_IOCTL_TX_SUPPORT: + { + fm_s32 tx_support = -1; + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_TX_SUPPORT......\n"); + + ret = fm_tx_support(fm,&tx_support); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "fm_tx_support err\n"); + } + if (copy_to_user((void*)arg, &tx_support, sizeof(fm_s32))) + { + WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + case FM_IOCTL_POWERUP_TX: + { + struct fm_tune_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP_TX:0\n"); + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + ret = fm_powerup_tx(fm, &parm); + if (ret < 0) { + goto out; + } + ret = fm_tune_tx(fm, &parm); + if (ret < 0) goto out; + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP_TX:1\n"); + break; + } + + case FM_IOCTL_TUNE_TX: + { + struct fm_tune_parm parm; + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_TX:0\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + ret = fm_tune_tx(fm, &parm); + if (ret < 0) { + goto out; + } + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_TX:1\n"); + break; + } + case FM_IOCTL_RDSTX_SUPPORT: + { + fm_s32 rds_tx_support = -1; + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_RDSTX_SUPPORT......\n"); + + ret = fm_rdstx_support(fm,&rds_tx_support); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "fm_rdstx_support err\n"); + } + if (copy_to_user((void*)arg, &rds_tx_support, sizeof(fm_s32))) + { + WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_RDSTX_ENABLE: + { + fm_s32 rds_tx_enable = -1; + WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_RDSTX_ENABLE......\n"); + + ret = fm_rdstx_enable(fm,&rds_tx_enable); + if(ret) + { + WCN_DBG(FM_ERR | MAIN, "fm_rdstx_enable err\n"); + } + if (copy_to_user((void*)arg, &rds_tx_enable, sizeof(fm_s32))) + { + WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_RDS_TX: + { + struct fm_rds_tx_parm parm; + WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_RDS_TX......\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_rds_tx_parm))) + { + WCN_DBG(FM_ALT | MAIN, "RDS Tx, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_rds_tx(fm, &parm); + if(ret) + { + WCN_DBG(FM_ALT | MAIN, "fm_rds_tx err\n"); + } + + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_rds_tx_parm))){ + WCN_DBG(FM_ALT | MAIN, "RDS Tx, copy_to_user err\n"); + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_TX_SCAN: + { + struct fm_tx_scan_parm parm; + WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_TX_SCAN......\n"); + + if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tx_scan_parm))){ + WCN_DBG(FM_ALT | MAIN,"copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + ret = fm_tx_scan(fm, &parm); + if(ret < 0){ + WCN_DBG(FM_ERR | MAIN,"FM_IOCTL_TX_SCAN failed\n"); + } + if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tx_scan_parm))){ + WCN_DBG(FM_ALT | MAIN,"copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + + default: + ret = -EPERM; + } + +out: + if (ret == -FM_EFW) { + // subsystem reset + fm_subsys_reset(fm); + } + + return ret; +} + +static loff_t fm_ops_lseek(struct file *filp, loff_t off, fm_s32 whence) +{ + struct fm *fm = filp->private_data; + + if (whence == SEEK_END) { + fm_hwscan_stop(fm); + } else if (whence == SEEK_SET) { + FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY); + } + + return off; +} + +static ssize_t fm_ops_read(struct file *filp, char *buf, size_t len, loff_t *off) +{ + struct fm *fm = filp->private_data; + fm_s32 copy_len = 0; + + if (!fm) { + WCN_DBG(FM_ALT | MAIN, "fm_read invalid fm pointer\n"); + return 0; + } + + if (!buf || len < sizeof(rds_t)) { + WCN_DBG(FM_DBG | MAIN, "fm_read invliad buf\n"); + return 0; + } + + //block when FM is resetting + while (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) { + msleep_interruptible(100); + } + + copy_len = sizeof(rds_t); + + return fm_rds_read(fm, buf, copy_len); +} + +static fm_s32 fm_ops_open(struct inode *inode, struct file *filp) +{ + fm_s32 ret = 0; + struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev); + struct fm *fm = container_of(plat, struct fm, platform); + + WCN_DBG(FM_NTC | MAIN, "fm_ops_open:0\n"); + if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) { + WCN_DBG(FM_ALT| MAIN, "FM subsys is resetting, retry later\n"); + ret = -FM_ESRST; + return ret; + } + + ret = fm_open(fm); + filp->private_data = fm; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_open:1\n"); + return ret; +} + +static fm_s32 fm_ops_release(struct inode *inode, struct file *filp) +{ +// fm_s32 ret = 0; +// struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev); +// struct fm *fm = container_of(plat, struct fm, platform); + +// WCN_DBG(FM_NTC | MAIN, "fm_ops_release:0\n"); + //fm_close(fm); + filp->private_data = NULL; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_release\n"); + return 0; +} + +static fm_s32 fm_ops_flush(struct file *filp,fl_owner_t Id) +{ + fm_s32 ret = 0; + struct fm *fm = filp->private_data; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_flush:0\n"); + fm_close(fm); + filp->private_data = fm; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_flush:1\n"); + return ret; +} + +static fm_s32 fm_proc_read(char *page, char **start, off_t off, fm_s32 count, fm_s32 *eof, void *data) +{ + fm_s32 cnt = 0; + struct fm *fm = g_fm; + + WCN_DBG(FM_NTC | MAIN, "Enter fm_proc_read.\n"); + + if (off != 0) + return 0; + + if (!fm) { + WCN_DBG(FM_ALT | MAIN, "para err\n"); + return 0; + } + + if (fm->chipon && (fm_pwr_state_get(fm) == FM_PWR_RX_ON)) + { + cnt = sprintf(page, "1\n"); + WCN_DBG(FM_NTC | MAIN, " FM_PWR_RX_ON\n"); + } + else if (fm->chipon && (fm_pwr_state_get(fm) == FM_PWR_TX_ON)) + { + WCN_DBG(FM_NTC | MAIN, " FM_PWR_TX_ON\n"); + cnt = sprintf(page, "2\n"); + } + else + { + cnt = sprintf(page, "0\n"); + } + + *eof = 1; + WCN_DBG(FM_NTC | MAIN, "Leave fm_proc_read. cnt = %d\n", cnt); + return cnt; +} + +static fm_s32 fm_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + fm_s8 tmp_buf[50] = {0}; + fm_u32 copysize; + + copysize = (count < (sizeof(tmp_buf) - 1)) ? count : (sizeof(tmp_buf) - 1); + + WCN_DBG(FM_NTC | MAIN, "fm_proc_write:0\n"); + if (copy_from_user(tmp_buf, buffer, copysize)) { + WCN_DBG(FM_ERR | MAIN, "failed copy_from_user\n"); + return -EFAULT; + } + + if (strncmp(tmp_buf, "subsys reset", strlen("subsys reset")) == 0) { + fm_subsys_reset(g_fm); + return count; + } + + if (!fm_cust_config_setup(tmp_buf)) { + WCN_DBG(FM_NTC | MAIN, "get config form %s ok\n", tmp_buf); + return count; + } + + if (sscanf(tmp_buf, "%x", &g_dbg_level) != 1) { + WCN_DBG(FM_ERR | MAIN, "failed g_dbg_level = 0x%x\n", g_dbg_level); + return -EFAULT; + } + + WCN_DBG(FM_NTC | MAIN, "fm_proc_write:1 g_dbg_level = 0x%x\n", g_dbg_level); + return count; +} + +#define FM_DEV_STATIC_ALLOC +#define FM_DEV_MAJOR 193 +static int FM_major = FM_DEV_MAJOR; /* dynamic allocation */ + +static fm_s32 fm_cdev_setup(struct fm *fm) +{ + fm_s32 ret = 0; + struct fm_platform *plat = &fm->platform; + +#ifdef FM_DEV_STATIC_ALLOC + /*static allocate chrdev*/ + plat->dev_t = MKDEV(FM_major, 0); + ret = register_chrdev_region(plat->dev_t, 1, FM_NAME); + + if (ret) { + WCN_DBG(FM_ERR | MAIN, "%s():fail to register chrdev\n", __func__); + return ret; + } + +#endif + +#ifndef FM_DEV_STATIC_ALLOC + ret = alloc_chrdev_region(&plat->dev_t, 0, 1, FM_NAME); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "alloc dev_t failed\n"); + return ret; + } + +#endif + + WCN_DBG(FM_NTC | MAIN, "alloc %s:%d:%d\n", FM_NAME, MAJOR(plat->dev_t), MINOR(plat->dev_t)); + + cdev_init(&plat->cdev, &fm_ops); + + plat->cdev.owner = THIS_MODULE; + plat->cdev.ops = &fm_ops; + + ret = cdev_add(&plat->cdev, plat->dev_t, 1); + + if (ret) { + WCN_DBG(FM_ALT | MAIN, "add dev_t failed\n"); + return ret; + } + +#ifndef FM_DEV_STATIC_ALLOC + plat->cls = class_create(THIS_MODULE, FM_NAME); + + if (IS_ERR(plat->cls)) { + ret = PTR_ERR(plat->cls); + WCN_DBG(FM_ALT | MAIN, "class_create err:%d\n", ret); + return ret; + } + + plat->dev = device_create(plat->cls, NULL, plat->dev_t, NULL, FM_NAME); +#endif + + return ret; +} + +static fm_s32 fm_cdev_destroy(struct fm *fm) +{ + FMR_ASSERT(fm); + + device_destroy(fm->platform.cls, fm->platform.dev_t); + class_destroy(fm->platform.cls); + cdev_del(&fm->platform.cdev); + unregister_chrdev_region(fm->platform.dev_t, 1); + + return 0; +} + +static fm_s32 fm_mod_init(fm_u32 arg) +{ + fm_s32 ret = 0; + struct fm *fm = NULL; + + fm = fm_dev_init(0); + + if (!fm) { + ret = -ENOMEM; + goto ERR_EXIT; + } + + if ((ret = fm_cdev_setup(fm))) { + goto ERR_EXIT; + } + + //fm proc file create "/proc/fm" + g_fm_proc = create_proc_entry(FM_PROC_FILE, 0444, NULL); + + if (g_fm_proc == NULL) { + WCN_DBG(FM_ALT | MAIN, "create_proc_entry failed\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + g_fm_proc->read_proc = fm_proc_read; + g_fm_proc->write_proc = fm_proc_write; + WCN_DBG(FM_NTC | MAIN, "create_proc_entry success\n"); + } + + g_fm = fm; + return 0; + +ERR_EXIT: + + if (fm) { + fm_cdev_destroy(fm); + fm_dev_destroy(fm); + } + + remove_proc_entry(FM_PROC_FILE, NULL); + return ret; +} + +static fm_s32 fm_mod_destroy(struct fm *fm) +{ + fm_s32 ret = 0; + + FMR_ASSERT(fm); + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + remove_proc_entry(FM_PROC_FILE, NULL); + fm_cdev_destroy(fm); + fm_dev_destroy(fm); + + return ret; +} + +static fm_s32 mt_fm_probe(struct platform_device *pdev) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + ret = fm_mod_init(0); + + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm mod init err\n"); + return -ENOMEM; + } + + return ret; +} + +static fm_s32 mt_fm_remove(struct platform_device *pdev) +{ + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + fm_mod_destroy(g_fm); + g_fm = NULL; + return 0; +} + +static struct platform_device mt_fm_device = { + .name = FM_NAME, + .id = -1, +}; + +//platform driver entry +static struct platform_driver mt_fm_dev_drv = { + .probe = mt_fm_probe, + .remove = mt_fm_remove, + .driver = { + .name = FM_NAME, + .owner = THIS_MODULE, + } +}; + +static fm_s32 __init mt_fm_init(void) +{ + fm_s32 ret = 0; + + ret = fm_env_setup(); + + if (ret) { + fm_env_destroy(); + return ret; + } + + //register fm device to platform bus + ret = platform_device_register(&mt_fm_device); + + if (ret) { + return ret; + } + + //register fm driver to platform bus + ret = platform_driver_register(&mt_fm_dev_drv); + + if (ret) { + return ret; + } + + WCN_DBG(FM_NTC | MAIN, "6. fm platform driver registered\n"); + return ret; +} + +static void __exit mt_fm_exit(void) +{ + platform_driver_unregister(&mt_fm_dev_drv); + fm_env_destroy(); +} + + +EXPORT_SYMBOL(g_dbg_level); +module_init(mt_fm_init); +module_exit(mt_fm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek FM Driver"); +MODULE_AUTHOR("Hongcheng "); diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c new file mode 100755 index 000000000000..f69d3fcce399 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c @@ -0,0 +1,146 @@ +/* fm_patch.c + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * FM Radio Driver -- patch functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" + +/* + * fm_file_exist - test file + * @filename - source file name + * If exsit, return 0, else error code + */ +fm_s32 fm_file_exist(const fm_s8 *filename) +{ + fm_s32 ret = 0; + mm_segment_t old_fs; + struct file *fp = NULL; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + fp = filp_open(filename, O_RDONLY, 0); + + if (IS_ERR(fp)) { + WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename); + set_fs(old_fs); + return -FM_EPATCH; + } else { + WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename); + } + + if (fp) { + filp_close(fp, NULL); + } + + set_fs(old_fs); + + return ret; +} + + +/* + * fm_file_read - read FM DSP patch/coeff/hwcoeff/rom binary file + * @filename - source file name + * @dst - target buffer + * @len - desired read length + * @position - the read position + * If success, return read length in bytes, else error code + */ +fm_s32 fm_file_read(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 position) +{ + fm_s32 ret = 0; + loff_t pos = position; + mm_segment_t old_fs; + struct file *fp = NULL; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + fp = filp_open(filename, O_RDONLY, 0); + + if (IS_ERR(fp)) { + WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename); + set_fs(old_fs); + return -FM_EPATCH; + } else { + WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename); + } + + ret = vfs_read(fp, (char __user *)dst, len, &pos); + + if (ret < 0) { + WCN_DBG(FM_ERR | CHIP, "read \"%s\" failed\n", filename); + } else if (ret < len) { + WCN_DBG(FM_NTC | CHIP, "read \"%s\" part data\n", filename); + } else { + WCN_DBG(FM_NTC | CHIP, "read \"%s\" full data\n", filename); + } + + if (fp) { + filp_close(fp, NULL); + } + + set_fs(old_fs); + + return ret; +} + + +fm_s32 fm_file_write(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 *ppos) +{ + fm_s32 ret = 0; + loff_t pos = *ppos; + mm_segment_t old_fs; + struct file *fp = NULL; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + fp = filp_open(filename, O_CREAT | O_RDWR, 0); + + if (IS_ERR(fp)) { + WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename); + set_fs(old_fs); + return -FM_EPATCH; + } else { + WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename); + } + + WCN_DBG(FM_NTC | CHIP, "\"%s\" old pos %d\n", filename, (int)pos); + ret = vfs_write(fp, (char __user *)dst, len, &pos); + WCN_DBG(FM_NTC | CHIP, "\"%s\" new pos %d\n", filename, (int)pos); + *ppos = pos; + if (ret < 0) { + WCN_DBG(FM_ERR | CHIP, "write \"%s\" failed\n", filename); + } else if (ret < len) { + WCN_DBG(FM_NTC | CHIP, "write \"%s\" data\n", filename); + } + + if (fp) { + filp_close(fp, NULL); + } + + set_fs(old_fs); + + return ret; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c new file mode 100755 index 000000000000..e890243846ac --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c @@ -0,0 +1,1867 @@ +/* fm_rds_parser.c + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +//static rds_ps_state_machine_t ps_state_machine = RDS_PS_START; +//static rds_rt_state_machine_t rt_state_machine = RDS_RT_START; +struct fm_state_machine { + fm_s32 state; + fm_s32(*state_get)(struct fm_state_machine *thiz); + fm_s32(*state_set)(struct fm_state_machine *thiz, fm_s32 new_state); +}; + +static fm_s32 fm_state_get(struct fm_state_machine *thiz) +{ + return thiz->state; +} + +static fm_s32 fm_state_set(struct fm_state_machine *thiz, fm_s32 new_state) +{ + return thiz->state = new_state; +} + +#define STATE_SET(a, s) \ +{ \ + if((a)->state_set){ \ + (a)->state_set((a), (s)); \ + } \ +} + +#define STATE_GET(a) \ +({ \ + fm_s32 __ret = 0; \ + if((a)->state_get){ \ + __ret = (a)->state_get((a)); \ + } \ + __ret; \ +}) + +static fm_u16(*rds_get_freq)(void) = NULL; + +//RDS spec related handle flow +/* + * rds_cnt_get + * To get rds group count form raw data + * If success return 0, else return error code +*/ +static fm_s32 rds_cnt_get(struct rds_rx_t *rds_raw, fm_s32 raw_size, fm_s32 *cnt) +{ + fm_s32 gap = sizeof(rds_raw->cos) + sizeof(rds_raw->sin); + + FMR_ASSERT(rds_raw); + FMR_ASSERT(cnt); + *cnt = (raw_size - gap) / sizeof(rds_packet_t); + WCN_DBG(FM_INF | RDSC, "group cnt=%d\n", *cnt); + + return 0; +} + +/* + * rds_grp_get + * To get rds group[n] data form raw data with index + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_get(fm_u16 *dst, struct rds_rx_t *raw, fm_s32 idx) +{ + FMR_ASSERT(dst); + FMR_ASSERT(raw); + + if (idx > (MAX_RDS_RX_GROUP_CNT - 1)) { + return -FM_EPARA; + } + + dst[0] = raw->data[idx].blkA; + dst[1] = raw->data[idx].blkB; + dst[2] = raw->data[idx].blkC; + dst[3] = raw->data[idx].blkD; + dst[4] = raw->data[idx].crc; + dst[5] = raw->data[idx].cbc; + + WCN_DBG(FM_NTC | RDSC, "BLOCK:%04x %04x %04x %04x, CRC:%04x CBC:%04x\n", dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]); + + return 0; +} + +/* + * rds_checksum_check + * To check CRC rerult, if OK, *valid=fm_true, else *valid=fm_false + * If success return 0, else return error code +*/ +static fm_s32 rds_checksum_check(fm_u16 crc, fm_s32 mask, fm_bool *valid) +{ + FMR_ASSERT(valid); + + if ((crc & mask) == mask) { + *valid = fm_true; + } else { + *valid = fm_false; + } + + return 0; +} + +/* + * rds_cbc_get - To get block_n's correct bit count form cbc + * @cbc, the group's correct bit count + * @blk, target the block + * + * If success, return block_n's cbc, else error code +*/ +/* +static fm_s32 rds_cbc_get(fm_u16 cbc, enum rds_blk_t blk) +{ + int ret = 0; + + switch (blk) { + case RDS_BLK_A: + ret = (cbc & 0xF000) >> 12; + break; + case RDS_BLK_B: + ret = (cbc & 0x0F00) >> 8; + break; + case RDS_BLK_C: + ret = (cbc & 0x00F0) >> 4; + break; + case RDS_BLK_D: + ret = (cbc & 0x000F) >> 0; + break; + default: + break; + } + + WCN_DBG(FM_INF | RDSC, "group cbc=0x%04x\n", cbc); + return ret; +} +*/ +/* + * rds_event_set + * To set rds event, and user space can use this flag to juge which event happened + * If success return 0, else return error code +*/ +static fm_s32 rds_event_set(fm_u16 *events, fm_s32 event_mask) +{ + FMR_ASSERT(events); + WCN_DBG(FM_NTC | RDSC, "rds set event[%x->%x]\n", event_mask,*events); + *events |= event_mask; + + return 0; +} + +/* + * rds_flag_set + * To set rds event flag, and user space can use this flag to juge which event happened + * If success return 0, else return error code +*/ +static fm_s32 rds_flag_set(fm_u32 *flags, fm_s32 flag_mask) +{ + FMR_ASSERT(flags); + *flags |= flag_mask; + WCN_DBG(FM_NTC | RDSC, "rds set flag[%x->%x]\n", flag_mask,*flags); + + return 0; +} + +/* + * rds_grp_type_get + * To get rds group type form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_type_get(fm_u16 crc, fm_u16 blk, fm_u8 *type, fm_u8 *subtype) +{ + fm_bool valid = fm_false; + + FMR_ASSERT(type); + FMR_ASSERT(subtype); + //to get the group type from block B + rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); + + if (valid == fm_true) { + *type = (blk & 0xF000) >> 12; //Group type(4bits) + *subtype = (blk & 0x0800) >> 11; //version code(1bit), 0=vesionA, 1=versionB + } else { + WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n"); + return -FM_ECRC; + } + + WCN_DBG(FM_DBG | RDSC, "Type=%d, subtype:%s\n", (fm_s32)*type, *subtype ? "version B" : "version A"); + return 0; +} + +/* + * rds_grp_counter_add + * @type -- group type, rang: 0~15 + * @subtype -- sub group type, rang:0~1 + * + * add group counter, g0a~g15b + * we use type value as the index + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_counter_add(fm_u8 type, fm_u8 subtype, struct rds_group_cnt_t *gc) +{ + FMR_ASSERT(gc); + + if (type > 15) { + return -FM_EPARA; + } + + switch (subtype) { + case RDS_GRP_VER_A: + gc->groupA[type]++; + break; + case RDS_GRP_VER_B: + gc->groupB[type]++; + break; + default: + return -FM_EPARA; + break; + } + + gc->total++; + WCN_DBG(FM_INF | RDSC, "group counter:%d\n", (fm_s32)gc->total); + return 0; +} + +/* + * rds_grp_counter_get + * + * read group counter , g0a~g15b + * If success return 0, else return error code +*/ +extern fm_s32 rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src) +{ + FMR_ASSERT(dst); + FMR_ASSERT(src); + fm_memcpy(dst, src, sizeof(struct rds_group_cnt_t)); + WCN_DBG(FM_DBG | RDSC, "rds gc get[total=%d]\n", (fm_s32)dst->total); + return 0; +} + +/* + * rds_grp_counter_reset + * + * clear group counter to 0, g0a~g15b + * If success return 0, else return error code +*/ +extern fm_s32 rds_grp_counter_reset(struct rds_group_cnt_t *gc) +{ + FMR_ASSERT(gc); + fm_memset(gc, 0, sizeof(struct rds_group_cnt_t)); + return 0; +} + +extern fm_s32 rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len) +{ + FMR_ASSERT(new_log); + + if (thiz->len < thiz->size) { + new_len = (new_len < sizeof(struct rds_rx_t)) ? new_len : sizeof(struct rds_rx_t); + fm_memcpy(&(thiz->rds_log[thiz->in]), new_log, new_len); + thiz->log_len[thiz->in] = new_len; + thiz->in = (thiz->in + 1) % thiz->size; + thiz->len++; + WCN_DBG(FM_DBG | RDSC, "add a new log[len=%d]\n", thiz->len); + } else { + WCN_DBG(FM_WAR | RDSC, "rds log buf is full\n"); + return -FM_ENOMEM; + } + + return 0; +} + +extern fm_s32 rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len) +{ + FMR_ASSERT(dst); + FMR_ASSERT(dst_len); + + if (thiz->len > 0) { + *dst_len = thiz->log_len[thiz->out]; + *dst_len = (*dst_len < sizeof(struct rds_rx_t)) ? *dst_len : sizeof(struct rds_rx_t); + fm_memcpy(dst, &(thiz->rds_log[thiz->out]), *dst_len); + thiz->out = (thiz->out + 1) % thiz->size; + thiz->len--; + WCN_DBG(FM_DBG | RDSC, "del a new log[len=%d]\n", thiz->len); + } else { + *dst_len = 0; + WCN_DBG(FM_WAR | RDSC, "rds log buf is empty\n"); + } + + return 0; +} + +/* + * rds_grp_pi_get + * To get rds group pi code form blockA + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_pi_get(fm_u16 crc, fm_u16 blk, fm_u16 *pi, fm_bool *dirty) +{ + fm_s32 ret = 0; + fm_bool valid = fm_false; + + FMR_ASSERT(pi); + FMR_ASSERT(dirty); + + //to get the group pi code from block A + ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_A, &valid); + + if (valid == fm_true) { + if (*pi != blk) { + //PI=program Identication + *pi = blk; + *dirty = fm_true; // yes, we got new PI code + } else { + *dirty = fm_false; // PI is the same as last one + } + } else { + WCN_DBG(FM_WAR | RDSC, "Block0 CRC err\n"); + return -FM_ECRC; + } + + WCN_DBG(FM_INF | RDSC, "PI=0x%04x, %s\n", *pi, *dirty ? "new" : "old"); + return ret; +} + +/* + * rds_grp_pty_get + * To get rds group pty code form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_pty_get(fm_u16 crc, fm_u16 blk, fm_u8 *pty, fm_bool *dirty) +{ + fm_s32 ret = 0; +// fm_bool valid = fm_false; + + FMR_ASSERT(pty); + FMR_ASSERT(dirty); + + //to get PTY code from block B +// ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); + +// if (valid == fm_false) { +// WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n"); +// return -FM_ECRC; +// } + + if (*pty != ((blk & 0x03E0) >> 5)) { + //PTY=Program Type Code + *pty = (blk & 0x03E0) >> 5; + *dirty = fm_true; // yes, we got new PTY code + } else { + *dirty = fm_false; // PTY is the same as last one + } + + WCN_DBG(FM_INF | RDSC, "PTY=%d, %s\n", (fm_s32)*pty, *dirty ? "new" : "old"); + return ret; +} + +/* + * rds_grp_tp_get + * To get rds group tp code form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_grp_tp_get(fm_u16 crc, fm_u16 blk, fm_u8 *tp, fm_bool *dirty) +{ + fm_s32 ret = 0; +// fm_bool valid = fm_false; + + FMR_ASSERT(tp); + FMR_ASSERT(dirty); + + //to get TP code from block B +// ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); + +// if (valid == fm_false) { +// WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n"); +// return -FM_ECRC; +// } + + if (*tp != ((blk&0x0400) >> 10)) { + //Tranfic Program Identification + *tp = (blk & 0x0400) >> 10; + *dirty = fm_true; // yes, we got new TP code + } else { + *dirty = fm_false; // TP is the same as last one + } + + WCN_DBG(FM_NTC | RDSC, "TP=%d, %s\n", (fm_s32)*tp, *dirty ? "new" : "old"); + return ret; +} + +/* + * rds_g0_ta_get + * To get rds group ta code form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_g0_ta_get(fm_u16 blk, fm_u8 *ta, fm_bool *dirty) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ta); + FMR_ASSERT(dirty); + + //TA=Traffic Announcement code + if (*ta != ((blk & 0x0010) >> 4)) { + *ta = (blk & 0x0010) >> 4; + *dirty = fm_true; // yes, we got new TA code + } else { + *dirty = fm_false; // TA is the same as last one + } + + WCN_DBG(FM_INF | RDSC, "TA=%d, %s\n", (fm_s32)*ta, *dirty ? "new" : "old"); + return ret; +} + +/* + * rds_g0_music_get + * To get music-speech switch code form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_g0_music_get(fm_u16 blk, fm_u8 *music, fm_bool *dirty) +{ + fm_s32 ret = 0; + + FMR_ASSERT(music); + FMR_ASSERT(dirty); + + //M/S=music speech switch code + if (*music != ((blk & 0x0008) >> 3)) { + *music = (blk & 0x0008) >> 3; + *dirty = fm_true; // yes, we got new music code + } else { + *dirty = fm_false; // music is the same as last one + } + + WCN_DBG(FM_INF | RDSC, "Music=%d, %s\n", (fm_s32)*music, *dirty ? "new" : "old"); + return ret; +} + +/* + * rds_g0_ps_addr_get + * To get ps addr form blockB, blkB b0~b1 + * If success return 0, else return error code +*/ +static fm_s32 rds_g0_ps_addr_get(fm_u16 blkB, fm_u8 *addr) +{ + FMR_ASSERT(addr); + *addr = (fm_u8)blkB & 0x03; + + WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr); + return 0; +} + +/* + * rds_g0_di_flag_get + * To get DI segment flag form blockB, blkB b2 + * If success return 0, else return error code +*/ +static fm_s32 rds_g0_di_flag_get(fm_u16 blkB, fm_u8 *flag) +{ + FMR_ASSERT(flag); + *flag = (fm_u8)((blkB & 0x0004) >> 2); + + WCN_DBG(FM_INF | RDSC, "flag=0x%02x\n", *flag); + return 0; +} + +static fm_s32 rds_g0_ps_get(fm_u16 crc, fm_u16 blkD, fm_u8 addr, fm_u8 *buf) +{ +// fm_bool valid = fm_false; + fm_s32 idx = 0; + + FMR_ASSERT(buf); + + //ps segment addr rang 0~3 + if (addr > 0x03) { + WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr); + return -FM_EPARA; + } else { + idx = 2 * addr; + } + + buf[idx] = blkD >> 8; + buf[idx+1] = blkD & 0xFF; + #if 0 + rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid); + + if (valid == fm_true) { + buf[idx] = blkD >> 8; + buf[idx+1] = blkD & 0xFF; + } else { + WCN_DBG(FM_ERR | RDSC, "ps crc check err\n"); + return -FM_ECRC; + } + #endif + + WCN_DBG(FM_NTC | RDSC, "PS:addr[%02x]:0x%02x 0x%02x\n", addr, buf[idx], buf[idx+1]); + return 0; +} + +/* + * rds_g0_ps_cmp + * this function is the most importent flow for PS parsing + * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf + * 2.Check wether we got a full segment + * If success return 0, else return error code +*/ +static fm_s32 rds_g0_ps_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 *fresh, + fm_u8 *once, fm_u8 *twice, /*fm_bool *valid,*/fm_u8 *bm) +{ + fm_s32 ret = 0,indx; + // fm_s32 i = 0; + //fm_s32 j = 0; + // fm_s32 cnt = 0; + fm_u8 AF_H, AF_L,PS_Num; + //fm_u8 corrBitCnt_BlkB, corrBitCnt_BlkD; + static fm_s8 Pre_PS_Num = -1; + + FMR_ASSERT(fresh); + FMR_ASSERT(once); + FMR_ASSERT(twice); +// FMR_ASSERT(valid); + + //j = 2; // PS segment width + PS_Num = addr; + //corrBitCnt_BlkB = rds_cbc_get(cbc, RDS_BLK_B); + //corrBitCnt_BlkD = rds_cbc_get(cbc, RDS_BLK_D); + + AF_H = once[2*PS_Num]; + AF_L = once[2*PS_Num+1]; + if((AF_H == fresh[2*PS_Num])&&(AF_L == fresh[2*PS_Num+1])) + { + twice[2*PS_Num] = once[2*PS_Num]; + twice[2*PS_Num+1] = once[2*PS_Num+1]; + *bm |= 1< 1) + { + for (indx=Pre_PS_Num+1; indxbm; +} + +static fm_s32 rds_bm_cnt_get(struct rds_bitmap *thiz) +{ + return thiz->cnt; +} + +#define FM_RDS_USE_SOLUTION_B + +static fm_s32 rds_bm_get_pos(struct rds_bitmap *thiz) +{ + fm_s32 i = thiz->max_addr; + fm_s32 j; + + j = 0; + + while (!(thiz->bm & (1 << i)) && (i > -1)) { + i--; + } + +#ifdef FM_RDS_USE_SOLUTION_B + for (j = i; j >= 0; j--) { + if (!(thiz->bm & (1 << j))) { + WCN_DBG(FM_NTC | RDSC, "uncomplete msg 0x%04x, delete it\n", thiz->bm); + return -1; + } + } +#endif + + return i; +} + +static fm_s32 rds_bm_clr(struct rds_bitmap *thiz) +{ + thiz->bm = 0x0000; + thiz->cnt = 0; + return 0; +} + +static fm_s32 rds_bm_cmp(struct rds_bitmap *bitmap1, struct rds_bitmap *bitmap2) +{ + return (fm_s32)(bitmap1->bm - bitmap2->bm); +} + +static fm_s32 rds_bm_set(struct rds_bitmap *thiz, fm_u8 addr) +{ + struct rds_bitmap bm_old; + + //text segment addr rang + if (addr > thiz->max_addr) { + WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr); + return -FM_EPARA; + } + + bm_old.bm = thiz->bm; + thiz->bm |= (1 << addr); //set bitmap + + if (!rds_bm_cmp(&bm_old, thiz)) { + thiz->cnt++; // multi get a segment + } else if (thiz->cnt > 0) { + thiz->cnt--; + } + + return 0; +} + + +/* + * rds_g2_rt_addr_get + * To get rt addr form blockB + * If success return 0, else return error code +*/ +static fm_s32 rds_g2_rt_addr_get(fm_u16 blkB, fm_u8 *addr) +{ + fm_s32 ret = 0; + + FMR_ASSERT(addr); + *addr = (fm_u8)blkB & 0x0F; + + WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr); + return ret; +} + +static fm_s32 rds_g2_txtAB_get(fm_u16 blk, fm_u8 *txtAB, fm_bool *dirty) +{ + fm_s32 ret = 0; + + FMR_ASSERT(txtAB); + FMR_ASSERT(dirty); + + if (*txtAB != ((blk&0x0010) >> 4)) + { + *txtAB = (blk & 0x0010) >> 4; + *dirty = fm_true; // yes, we got new txtAB code + WCN_DBG(FM_INF | RDSC, "changed! txtAB=%d\n", *txtAB); + } else { + *dirty = fm_false; // txtAB is the same as last one + } + + WCN_DBG(FM_INF | RDSC, "txtAB=%d, %s\n", *txtAB, *dirty ? "new" : "old"); + return ret; +} + +static fm_s32 rds_g2_rt_get(fm_u16 crc, fm_u8 subtype, fm_u16 blkC, fm_u16 blkD, fm_u8 addr, fm_u8 *buf) +{ + fm_s32 ret = 0; + fm_bool valid = fm_false; + fm_s32 idx = 0; + + FMR_ASSERT(buf); + + //text segment addr rang 0~15 + if (addr > 0x0F) { + WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr); + ret = -FM_EPARA; + return ret; + } + + switch (subtype) { + case RDS_GRP_VER_A: + idx = 4 * addr; + ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_C | FM_RDS_GDBK_IND_D, &valid); + + if (valid == fm_true) { + buf[idx] = blkC >> 8; + buf[idx+1] = blkC & 0xFF; + buf[idx+2] = blkD >> 8; + buf[idx+3] = blkD & 0xFF; + } else { + WCN_DBG(FM_ERR | RDSC, "rt crc check err\n"); + ret = -FM_ECRC; + } + + break; + case RDS_GRP_VER_B: + idx = 2 * addr; + ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid); + + if (valid == fm_true) { + buf[idx] = blkD >> 8; + buf[idx+1] = blkD & 0xFF; + } else { + WCN_DBG(FM_ERR | RDSC, "rt crc check err\n"); + ret = -FM_ECRC; + } + + break; + default: + break; + } + + WCN_DBG(FM_NTC | RDSC, "fresh addr[%02x]:0x%02x%02x 0x%02x%02x\n", addr, buf[idx], buf[idx+1], buf[idx+2], buf[idx+3]); + return ret; +} + +static fm_s32 rds_g2_rt_get_len(fm_u8 subtype, fm_s32 pos, fm_s32 *len) +{ + fm_s32 ret = 0; + + FMR_ASSERT(len); + + if (subtype == RDS_GRP_VER_A) { + *len = 4 * (pos + 1); + } else { + *len = 2 * (pos + 1); + } + + return ret; +} + +/* + * rds_g2_rt_cmp + * this function is the most importent flow for RT parsing + * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf + * 2.Check wether we got a full segment, for typeA if copyed 4bytes to twice buf, for typeB 2bytes copyed to twice buf + * 3.Check wether we got the end of RT, if we got 0x0D + * 4.If we got the end, then caculate the RT lenth + * If success return 0, else return error code +*/ +static fm_s32 rds_g2_rt_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 subtype, fm_u8 *fresh, + fm_u8 *once, fm_u8 *twice, fm_bool *valid/*, fm_bool *end, fm_s32 *len*/) +{ + fm_s32 ret = 0; + fm_s32 i = 0; + fm_s32 j = 0; + fm_s32 cnt = 0; + + FMR_ASSERT(fresh); + FMR_ASSERT(once); + FMR_ASSERT(twice); + FMR_ASSERT(valid); +// FMR_ASSERT(end); + + j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width + + if (subtype == RDS_GRP_VER_A) { + //if (rds_cbc_get(cbc, RDS_BLK_C) == 0) + if(cbc==0) + { + once[j*addr+0] = fresh[j*addr+0]; + once[j*addr+1] = fresh[j*addr+1]; + //} + + //if (rds_cbc_get(cbc, RDS_BLK_D) == 0) + // { + once[j*addr+2] = fresh[j*addr+2]; + once[j*addr+3] = fresh[j*addr+3]; + } + } else if (subtype == RDS_GRP_VER_B) { + //if (rds_cbc_get(cbc, RDS_BLK_D) == 0) + if(cbc==0) + { + once[j*addr+0] = fresh[j*addr+0]; + once[j*addr+1] = fresh[j*addr+1]; + } + } + + for (i = 0; i < j; i++) { + if (fresh[j*addr+i] == once[j*addr+i]) { + twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times + cnt++; + WCN_DBG(FM_NTC | RDSC, "twice=%d\n", j*addr+i); + } else { + once[j*addr+i] = fresh[j*addr+i]; //use new val + WCN_DBG(FM_NTC | RDSC, "once=%d\n", j*addr+i); + } +#if 0 + //if we got 0x0D twice, it means a RT end + if (twice[j*addr+i] == 0x0D) { + *end = fm_true; + *len = j * addr + i + 1; //record the length of RT + WCN_DBG(FM_NTC | RDSC, "get 0D=%d\n", *len); + } +#endif + } + + //check if we got a valid segment 4bytes for typeA, 2bytes for typeB + if (cnt == j) { + *valid = fm_true; + } else { + *valid = fm_false; + } + + WCN_DBG(FM_INF | RDSC, "RT seg=%s\n", *valid == fm_true ? "fm_true" : "fm_false"); +// WCN_DBG(FM_INF | RDSC, "RT end=%s\n", *end == fm_true ? "fm_true" : "fm_false"); +// WCN_DBG(FM_INF | RDSC, "RT len=%d\n", *len); + return ret; +} + +/* + * rds_g2_rt_check_end + * check 0x0D end flag + * If we got the end, then caculate the RT lenth + * If success return 0, else return error code +*/ +static fm_s32 rds_g2_rt_check_end(fm_u8 addr, fm_u8 subtype, fm_u8 *twice,fm_bool *end) +{ + fm_s32 i = 0; + fm_s32 j = 0; + + FMR_ASSERT(twice); + FMR_ASSERT(end); + + j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width + *end = fm_false; + + for (i = 0; i < j; i++) + { + //if we got 0x0D twice, it means a RT end + if (twice[j*addr+i] == 0x0D) + { + *end = fm_true; + WCN_DBG(FM_NTC | RDSC, "get 0x0D\n"); + break; + } + } + + return 0; +} + +static fm_s32 rds_retrieve_g0_af(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + static fm_s16 preAF_Num = 0; + fm_u8 indx, indx2, AF_H, AF_L, num; + fm_s32 ret = 0; + fm_bool valid = fm_false; + fm_bool dirty = fm_false; + fm_u16 *event = &pstRDSData->event_status; + fm_u32 *flag = &pstRDSData->RDSFlag.flag_status; + +// ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid); + +// if (valid == fm_false) { +// WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n"); +// return -FM_ECRC; +// } + + ret = rds_g0_ta_get(block_data[1], &pstRDSData->RDSFlag.TA, &dirty); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get ta failed[ret=%d]\n", ret); + } else if (dirty == fm_true) { + ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TA code + ret = rds_flag_set(flag, RDS_FLAG_IS_TA); + } + + ret = rds_g0_music_get(block_data[1], &pstRDSData->RDSFlag.Music, &dirty); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get music failed[ret=%d]\n", ret); + } else if (dirty == fm_true) { + ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new MUSIC code + ret = rds_flag_set(flag, RDS_FLAG_IS_MUSIC); + } + + if ((pstRDSData->Switch_TP) && (pstRDSData->RDSFlag.TP) && !(pstRDSData->RDSFlag.TA)) { + ret = rds_event_set(event, RDS_EVENT_TAON_OFF); + } + + if (!SubType) { + //Type A + ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_C, &valid); + + if (valid == fm_false) { + WCN_DBG(FM_WAR | RDSC, "Group0 BlockC crc err\n"); + return -FM_ECRC; + } else { + AF_H = (block_data[2] & 0xFF00) >> 8; + AF_L = block_data[2] & 0x00FF; + + if ((AF_H > 224) && (AF_H < 250)) { + //Followed AF Number, see RDS spec Table 11, valid(224-249) + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_H:%d, AF_L:%d\n", AF_H, AF_L); + preAF_Num = AF_H - 224; //AF Number + + if (preAF_Num != pstRDSData->AF_Data.AF_Num) { + pstRDSData->AF_Data.AF_Num = preAF_Num; + pstRDSData->AF_Data.isAFNum_Get = 0; + } else { + //Get the same AFNum two times + pstRDSData->AF_Data.isAFNum_Get = 1; + } + + if ((AF_L < 205) && (AF_L > 0)) { + //See RDS Spec table 10, valid VHF + pstRDSData->AF_Data.AF[0][0] = AF_L + 875; //convert to 100KHz +#ifdef MTK_FM_50KHZ_SUPPORT + pstRDSData->AF_Data.AF[0][0] *= 10; +#endif + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][0]:%d\n", pstRDSData->AF_Data.AF[0][0]); + + if ((pstRDSData->AF_Data.AF[0][0]) != (pstRDSData->AF_Data.AF[1][0])) { + pstRDSData->AF_Data.AF[1][0] = pstRDSData->AF_Data.AF[0][0]; + } else { + if (pstRDSData->AF_Data.AF[1][0] != rds_get_freq()) + pstRDSData->AF_Data.isMethod_A = 1; + else + pstRDSData->AF_Data.isMethod_A = 0; + } + + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 isAFNum_Get:%d, isMethod_A:%d\n", pstRDSData->AF_Data.isAFNum_Get, pstRDSData->AF_Data.isMethod_A); + + //only one AF handle + if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.AF_Num == 1)) { + pstRDSData->AF_Data.Addr_Cnt = 0xFF; + pstRDSData->event_status |= RDS_EVENT_AF_LIST; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 RDS_EVENT_AF_LIST update\n"); + } + } + } + else if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.Addr_Cnt != 0xFF)) { + //AF Num correct + num = pstRDSData->AF_Data.AF_Num; + num = num >> 1; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +num:%d\n", num); + + //Put AF freq fm_s32o buffer and check if AF freq is repeat again + for (indx = 1; indx < (num + 1); indx++) { + if ((AF_H == (pstRDSData->AF_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AF_Data.AF[0][2*indx]))) { + WCN_DBG(FM_ERR | RDSC, "RetrieveGroup0 AF same as indx:%d\n", indx); + break; + } else if (!(pstRDSData->AF_Data.AF[0][2*indx-1])) { + //null buffer + pstRDSData->AF_Data.AF[0][2*indx-1] = AF_H + 875; //convert to 100KHz + pstRDSData->AF_Data.AF[0][2*indx] = AF_L + 875; + +#ifdef MTK_FM_50KHZ_SUPPORT + pstRDSData->AF_Data.AF[0][2*indx-1] *= 10; + pstRDSData->AF_Data.AF[0][2*indx] *= 10; +#endif + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][%d]:%d, AF[0][%d]:%d\n", + 2*indx - 1, pstRDSData->AF_Data.AF[0][2*indx-1], 2*indx, pstRDSData->AF_Data.AF[0][2*indx]); + break; + } + } + + num = pstRDSData->AF_Data.AF_Num; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 ++num:%d\n", num); + + if (num > 0) { + if ((pstRDSData->AF_Data.AF[0][num-1]) != 0) { + num = num >> 1; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +++num:%d\n", num); + + //arrange frequency from low to high:start + for (indx = 1; indx < num; indx++) { + for (indx2 = indx + 1; indx2 < (num + 1); indx2++) { + AF_H = pstRDSData->AF_Data.AF[0][2*indx-1]; + AF_L = pstRDSData->AF_Data.AF[0][2*indx]; + + if (AF_H > (pstRDSData->AF_Data.AF[0][2*indx2-1])) { + pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1]; + pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2]; + pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H; + pstRDSData->AF_Data.AF[0][2*indx2] = AF_L; + } else if (AF_H == (pstRDSData->AF_Data.AF[0][2*indx2-1])) { + if (AF_L > (pstRDSData->AF_Data.AF[0][2*indx2])) { + pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1]; + pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2]; + pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H; + pstRDSData->AF_Data.AF[0][2*indx2] = AF_L; + } + } + } + } + + //arrange frequency from low to high:end + //compare AF buff0 and buff1 data:start + num = pstRDSData->AF_Data.AF_Num; + indx2 = 0; + + for (indx = 0; indx < num; indx++) { + if ((pstRDSData->AF_Data.AF[1][indx]) == (pstRDSData->AF_Data.AF[0][indx])) { + if (pstRDSData->AF_Data.AF[1][indx] != 0) + indx2++; + } else + pstRDSData->AF_Data.AF[1][indx] = pstRDSData->AF_Data.AF[0][indx]; + } + + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 indx2:%d, num:%d\n", indx2, num); + + //compare AF buff0 and buff1 data:end + if (indx2 == num) { + pstRDSData->AF_Data.Addr_Cnt = 0xFF; + pstRDSData->event_status |= RDS_EVENT_AF_LIST; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_Num:%d\n", pstRDSData->AF_Data.AF_Num); + + for (indx = 0; indx < num; indx++) { + if ((pstRDSData->AF_Data.AF[1][indx]) == 0) { + pstRDSData->AF_Data.Addr_Cnt = 0x0F; + pstRDSData->event_status &= (~RDS_EVENT_AF_LIST); + } + } + } else + pstRDSData->AF_Data.Addr_Cnt = 0x0F; + } + } + } + } + } + + return ret; +} + +static fm_s32 rds_retrieve_g0_di(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + fm_u8 DI_Code, DI_Flag; + fm_s32 ret = 0; +// fm_bool valid = fm_false; + + fm_u16 *event = &pstRDSData->event_status; + fm_u32 *flag = &pstRDSData->RDSFlag.flag_status; + + //parsing Program service name segment (in BlockD) +// ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid); + +// if (valid == fm_false) { +// WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n"); +// return -FM_ECRC; +// } + + rds_g0_ps_addr_get(block_data[1], &DI_Code); + rds_g0_di_flag_get(block_data[1], &DI_Flag); + + switch (DI_Code) { + case 3: + + if (pstRDSData->RDSFlag.Stereo != DI_Flag) { + pstRDSData->RDSFlag.Stereo = DI_Flag; + ret = rds_event_set(event, RDS_EVENT_FLAGS); + ret = rds_flag_set(flag, RDS_FLAG_IS_STEREO); + } + + break; + case 2: + + if (pstRDSData->RDSFlag.Artificial_Head != DI_Flag) { + pstRDSData->RDSFlag.Artificial_Head = DI_Flag; + ret = rds_event_set(event, RDS_EVENT_FLAGS); + ret = rds_flag_set(flag, RDS_FLAG_IS_ARTIFICIAL_HEAD); + } + + break; + case 1: + + if (pstRDSData->RDSFlag.Compressed != DI_Flag) { + pstRDSData->RDSFlag.Compressed = DI_Flag; + ret = rds_event_set(event, RDS_EVENT_FLAGS); + ret = rds_flag_set(flag, RDS_FLAG_IS_COMPRESSED); + } + + break; + case 0: + + if (pstRDSData->RDSFlag.Dynamic_PTY != DI_Flag) { + pstRDSData->RDSFlag.Dynamic_PTY = DI_Flag; + ret = rds_event_set(event, RDS_EVENT_FLAGS); + ret = rds_flag_set(flag, RDS_FLAG_IS_DYNAMIC_PTY); + } + + break; + default: + break; + } + + return ret; +} + +static fm_s32 rds_retrieve_g0_ps(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + fm_u8 ps_addr; + fm_s32 ret = 0,i,num; + fm_bool valid = fm_false; +// fm_s32 pos = 0; + static struct fm_state_machine ps_sm = { + .state = RDS_PS_START, + .state_get = fm_state_get, + .state_set = fm_state_set, + }; +#if 0 + static struct rds_bitmap ps_bm = { + .bm = 0, + .cnt = 0, + .max_addr = 0x03, + .bm_get = rds_bm_get, + .bm_cnt_get = rds_bm_cnt_get, + .bm_set = rds_bm_set, + .bm_get_pos = rds_bm_get_pos, + .bm_clr = rds_bm_clr, + .bm_cmp = rds_bm_cmp, + }; +#endif + fm_u16 *event = &pstRDSData->event_status; + + //parsing Program service name segment (in BlockD) + ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid); + + if (valid == fm_false) { + WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n"); + return -FM_ECRC; + } + + rds_g0_ps_addr_get(block_data[1], &ps_addr); + + //PS parsing state machine run + while (1) { + switch (STATE_GET(&ps_sm)) { + case RDS_PS_START: + + if (rds_g0_ps_get(block_data[4], block_data[3], ps_addr, pstRDSData->PS_Data.PS[0])) { + STATE_SET(&ps_sm, RDS_PS_FINISH); //if CRC error, we should not do parsing + break; + } + + rds_g0_ps_cmp(ps_addr, block_data[5], pstRDSData->PS_Data.PS[0], + pstRDSData->PS_Data.PS[1], pstRDSData->PS_Data.PS[2], /*&valid,*/&pstRDSData->PS_Data.Addr_Cnt); + + // if (valid == fm_true) { + // ps_bm.bm_set(&ps_bm, ps_addr); + // } + + STATE_SET(&ps_sm, RDS_PS_DECISION); + break; + case RDS_PS_DECISION: + + if (pstRDSData->PS_Data.Addr_Cnt == 0x000F) //get max 8 chars + //ps shouldn't check bm_cnt + // || (ps_bm.bm_cnt_get(&ps_bm) > RDS_RT_MULTI_REV_TH)) { //repeate many times, but no end char get + { + //pos = ps_bm.bm_get_pos(&ps_bm); + STATE_SET(&ps_sm, RDS_PS_GETLEN); + } + else + { + STATE_SET(&ps_sm, RDS_PS_FINISH); + } + + break; + case RDS_PS_GETLEN: + + //if (pos == ps_bm.max_addr) + { + num=0; + WCN_DBG(FM_NTC | RDSC, "PS[3]=%x %x %x %x %x %x %x %x\n", + pstRDSData->PS_Data.PS[3][0], + pstRDSData->PS_Data.PS[3][1], + pstRDSData->PS_Data.PS[3][2], + pstRDSData->PS_Data.PS[3][3], + pstRDSData->PS_Data.PS[3][4], + pstRDSData->PS_Data.PS[3][5], + pstRDSData->PS_Data.PS[3][6], + pstRDSData->PS_Data.PS[3][7]); + for(i=0;i<8;i++)//compare with last PS. + { + if(pstRDSData->PS_Data.PS[3][i]==pstRDSData->PS_Data.PS[2][i]) + { + num++; + } + } + if(num != 8) + { + num=0; + for(i=0;i<8;i++) + { + if((pstRDSData->PS_Data.PS[2][i]==0x20)||(pstRDSData->PS_Data.PS[2][i]==0x0)) + { + num++; + } + } + if(num != 8) + { + fm_memcpy(pstRDSData->PS_Data.PS[3], pstRDSData->PS_Data.PS[2], 8); + rds_event_set(event, RDS_EVENT_PROGRAMNAME); //yes we got a new PS + WCN_DBG(FM_NTC | RDSC, "Yes, get an PS!\n"); + } + } + else + { + pstRDSData->PS_Data.Addr_Cnt=0; + //clear buf + fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8); + fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8); + fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8); + } + } +#if 0 + ps_bm.bm_clr(&ps_bm); + //clear buf + fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8); + fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8); + fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8); +#endif + STATE_SET(&ps_sm, RDS_PS_FINISH); + break; + case RDS_PS_FINISH: + STATE_SET(&ps_sm, RDS_PS_START); + goto out; + break; + default: + break; + } + } + +out: + return ret; +} + +static fm_s32 rds_retrieve_g0(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + fm_s32 ret = 0; + + ret = rds_retrieve_g0_af(block_data, SubType, pstRDSData); + + if (ret) { + return ret; + } + + ret = rds_retrieve_g0_di(block_data, SubType, pstRDSData); + + if (ret) { + return ret; + } + + ret = rds_retrieve_g0_ps(block_data, SubType, pstRDSData); + + if (ret) { + return ret; + } + + return ret; +} + +static fm_s32 rds_retrieve_g1(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + fm_u8 variant_code = (block_data[2] & 0x7000) >> 12; + fm_s32 ret = 0; + + if (variant_code == 0) { + pstRDSData->Extend_Country_Code = (fm_u8)block_data[2] & 0xFF; + WCN_DBG(FM_DBG | RDSC, "Extend_Country_Code:%d\n", pstRDSData->Extend_Country_Code); + } else if (variant_code == 3) { + pstRDSData->Language_Code = block_data[2] & 0xFFF; + WCN_DBG(FM_DBG | RDSC, "Language_Code:%d\n", pstRDSData->Language_Code); + } + + pstRDSData->Radio_Page_Code = block_data[1] & 0x001F; + pstRDSData->Program_Item_Number_Code = block_data[3]; + + return ret; +} + +static fm_s32 rds_retrieve_g2(fm_u16 *source, fm_u8 subtype, rds_t *target) +{ + fm_s32 ret = 0; + fm_u16 crc, cbc; + fm_u16 blkA, blkB, blkC, blkD; + fm_u8 *fresh, *once, *twice, *display; + fm_u16 *event; + fm_u32 *flag; + static struct fm_state_machine rt_sm = { + .state = RDS_RT_START, + .state_get = fm_state_get, + .state_set = fm_state_set, + }; + static struct rds_bitmap rt_bm = { + .bm = 0, + .cnt = 0, + .max_addr = 0xF, + .bm_get = rds_bm_get, + .bm_cnt_get = rds_bm_cnt_get, + .bm_set = rds_bm_set, + .bm_get_pos = rds_bm_get_pos, + .bm_clr = rds_bm_clr, + .bm_cmp = rds_bm_cmp, + }; + fm_u8 rt_addr = 0; + fm_bool txtAB_change = fm_false; //text AB flag 0 --> 1 or 1-->0 meas new RT incoming + fm_bool txt_end = fm_false; //0x0D means text end + fm_bool seg_ok = 0; + fm_s32 pos = 0; + fm_s32 rt_len = 0,indx=0,invalid_cnt=0; + fm_s32 bufsize = 0; + + FMR_ASSERT(source); + FMR_ASSERT(target); + //source + blkA = source[0]; + blkB = source[1]; + blkC = source[2]; + blkD = source[3]; + crc = source[4]; + cbc = source[5]; + //target + fresh = target->RT_Data.TextData[0]; + once = target->RT_Data.TextData[1]; + twice = target->RT_Data.TextData[2]; + display = target->RT_Data.TextData[3]; + event = &target->event_status; + flag = &target->RDSFlag.flag_status; + bufsize = sizeof(target->RT_Data.TextData[0]); + rt_bm.bm = target->RT_Data.Addr_Cnt; + + //get basic info: addr, txtAB + if (rds_g2_rt_addr_get(blkB, &rt_addr)) + return ret; + + if (rds_g2_txtAB_get(blkB, &target->RDSFlag.Text_AB, &txtAB_change)) + return ret; + if(txtAB_change == fm_true) + { + //clear buf + fm_memset(fresh, 0x20, bufsize); + fm_memset(once, 0x20, bufsize); + fm_memset(twice, 0x20, bufsize); + rt_bm.bm_clr(&rt_bm); + } + //RT parsing state machine run + while (1) { + switch (STATE_GET(&rt_sm)) { + case RDS_RT_START: + { +#if 0 + if (txtAB_change == fm_true) + { + STATE_SET(&rt_sm, RDS_RT_DECISION); + } + else +#endif + { + if (rds_g2_rt_get(crc, subtype, blkC, blkD, rt_addr, fresh) == 0) + { + //STATE_SET(&rt_sm, RDS_RT_FINISH); //if CRC error, we should not do parsing + //break; + rds_g2_rt_cmp(rt_addr, cbc, subtype, fresh, once, twice, + &seg_ok/*, &txt_end, &rt_len*/); + + if (seg_ok == fm_true) + { + rt_bm.bm_set(&rt_bm, rt_addr); + } + else//clear bitmap of rt_addr + { + rt_bm.bm &= ~(1< RDS_RT_MULTI_REV_TH))//repeate many times, but no end char get + { + pos = rt_bm.bm_get_pos(&rt_bm); + rds_g2_rt_get_len(subtype, pos, &rt_len); + STATE_SET(&rt_sm, RDS_RT_GETLEN); + } + else + { + STATE_SET(&rt_sm, RDS_RT_FINISH); + } + + break; + } + case RDS_RT_GETLEN: + + if (rt_len > 0 /*&& ((txt_end == fm_true) || (rt_bm.bm_get(&rt_bm) == 0xFFFF))*/) + { + for(indx=0; indxRT_Data.TextLength = rt_len; + rds_event_set(event, RDS_EVENT_LAST_RADIOTEXT); //yes we got a new RT + WCN_DBG(FM_NTC | RDSC, "Yes, get an RT! [len=%d]\n", rt_len); + } + rt_bm.bm_clr(&rt_bm); + //clear buf + fm_memset(fresh, 0x20, bufsize); + fm_memset(once, 0x20, bufsize); + fm_memset(twice, 0x20, bufsize); + } + else + WCN_DBG(FM_NTC | RDSC, "Get 0x20 RT %d\n", invalid_cnt); + } + +#if 0 + if (txtAB_change == fm_true) { + txtAB_change = fm_false; + //we need get new RT after show the old RT to the display + STATE_SET(&rt_sm, RDS_RT_START); + } + else +#endif + { + STATE_SET(&rt_sm, RDS_RT_FINISH); + } + break; + case RDS_RT_FINISH: + STATE_SET(&rt_sm, RDS_RT_START); + goto out; + break; + default: + break; + } + } + +out: + target->RT_Data.Addr_Cnt = rt_bm.bm; + return ret; +} + +static fm_s32 rds_retrieve_g4(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + fm_u16 year, month, k = 0, D2, minute; + fm_u32 MJD, D1; + fm_s32 ret = 0; + WCN_DBG(FM_DBG | RDSC, "RetrieveGroup4 %d\n", SubType); + + if (!SubType) { + //Type A + if ((block_data[4]&FM_RDS_GDBK_IND_C) && (block_data[4]&FM_RDS_GDBK_IND_D)) { + MJD = (fm_u32)(((block_data[1] & 0x0003) << 15) + ((block_data[2] & 0xFFFE) >> 1)); + year = (MJD * 100 - 1507820) / 36525; + month = (MJD * 10000 - 149561000 - 3652500 * year) / 306001; + + if ((month == 14) || (month == 15)) + k = 1; + + D1 = (fm_u32)((36525 * year) / 100); + D2 = (fm_u16)((306001 * month) / 10000); + pstRDSData->CT.Year = 1900 + year + k; + pstRDSData->CT.Month = month - 1 - k * 12; + pstRDSData->CT.Day = (fm_u16)(MJD - 14956 - D1 - D2); + pstRDSData->CT.Hour = ((block_data[2] & 0x0001) << 4) + ((block_data[3] & 0xF000) >> 12); + minute = (block_data[3] & 0x0FC0) >> 6; + + if (block_data[3]&0x0020) { + pstRDSData->CT.Local_Time_offset_signbit = 1; //0=+, 1=- + } + + pstRDSData->CT.Local_Time_offset_half_hour = block_data[3] & 0x001F; + + if (pstRDSData->CT.Minute != minute) { + pstRDSData->CT.Minute = (block_data[3] & 0x0FC0) >> 6; + pstRDSData->event_status |= RDS_EVENT_UTCDATETIME; + } + } + } + + return ret; +} + +static fm_s32 rds_retrieve_g14(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData) +{ + static fm_s16 preAFON_Num = 0; + fm_u8 TP_ON, TA_ON, PI_ON, PS_Num, AF_H, AF_L, indx, indx2, num; + fm_s32 ret = 0; + WCN_DBG(FM_DBG | RDSC, "RetrieveGroup14 %d\n", SubType); + //SubType = (*(block_data+1)&0x0800)>>11; + PI_ON = block_data[3]; + TP_ON = block_data[1] & 0x0010; + + if ((!SubType) && (block_data[4]&FM_RDS_GDBK_IND_C)) { + //Type A + PS_Num = block_data[1] & 0x000F; + + if (PS_Num < 4) { + for (indx = 0; indx < 2; indx++) { + pstRDSData->PS_ON[2*PS_Num] = block_data[2] >> 8; + pstRDSData->PS_ON[2*PS_Num+1] = block_data[2] & 0xFF; + } + } else if (PS_Num == 4) { + AF_H = (block_data[2] & 0xFF00) >> 8; + AF_L = block_data[2] & 0x00FF; + + if ((AF_H > 224) && (AF_H < 250)) { + //Followed AF Number + pstRDSData->AFON_Data.isAFNum_Get = 0; + preAFON_Num = AF_H - 224; + + if (pstRDSData->AFON_Data.AF_Num != preAFON_Num) { + pstRDSData->AFON_Data.AF_Num = preAFON_Num; + } else + pstRDSData->AFON_Data.isAFNum_Get = 1; + + if (AF_L < 205) { + pstRDSData->AFON_Data.AF[0][0] = AF_L + 875; + + if ((pstRDSData->AFON_Data.AF[0][0]) != (pstRDSData->AFON_Data.AF[1][0])) { + pstRDSData->AFON_Data.AF[1][0] = pstRDSData->AFON_Data.AF[0][0]; + } else { + pstRDSData->AFON_Data.isMethod_A = 1; + } + } + } + else if ((pstRDSData->AFON_Data.isAFNum_Get) && ((pstRDSData->AFON_Data.Addr_Cnt) != 0xFF)) { + //AF Num correct + num = pstRDSData->AFON_Data.AF_Num; + num = num >> 1; + + //Put AF freq fm_s32o buffer and check if AF freq is repeat again + for (indx = 1; indx < (num + 1); indx++) { + if ((AF_H == (pstRDSData->AFON_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AFON_Data.AF[0][2*indx]))) { + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup14 AFON same as indx:%d\n", indx); + break; + } else if (!(pstRDSData->AFON_Data.AF[0][2*indx-1])) { + //null buffer + pstRDSData->AFON_Data.AF[0][2*indx-1] = AF_H + 875; + pstRDSData->AFON_Data.AF[0][2*indx] = AF_L + 875; + break; + } + } + + num = pstRDSData->AFON_Data.AF_Num; + + if (num > 0) { + if ((pstRDSData->AFON_Data.AF[0][num-1]) != 0) { + num = num >> 1; + + //arrange frequency from low to high:start + for (indx = 1; indx < num; indx++) { + for (indx2 = indx + 1; indx2 < (num + 1); indx2++) { + AF_H = pstRDSData->AFON_Data.AF[0][2*indx-1]; + AF_L = pstRDSData->AFON_Data.AF[0][2*indx]; + + if (AF_H > (pstRDSData->AFON_Data.AF[0][2*indx2-1])) { + pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1]; + pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2]; + pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H; + pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L; + } else if (AF_H == (pstRDSData->AFON_Data.AF[0][2*indx2-1])) { + if (AF_L > (pstRDSData->AFON_Data.AF[0][2*indx2])) { + pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1]; + pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2]; + pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H; + pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L; + } + } + } + } + + //arrange frequency from low to high:end + //compare AF buff0 and buff1 data:start + num = pstRDSData->AFON_Data.AF_Num; + indx2 = 0; + + for (indx = 0; indx < num; indx++) { + if ((pstRDSData->AFON_Data.AF[1][indx]) == (pstRDSData->AFON_Data.AF[0][indx])) { + if (pstRDSData->AFON_Data.AF[1][indx] != 0) + indx2++; + } else + pstRDSData->AFON_Data.AF[1][indx] = pstRDSData->AFON_Data.AF[0][indx]; + } + + //compare AF buff0 and buff1 data:end + if (indx2 == num) { + pstRDSData->AFON_Data.Addr_Cnt = 0xFF; + pstRDSData->event_status |= RDS_EVENT_AFON_LIST; + + for (indx = 0; indx < num; indx++) { + if ((pstRDSData->AFON_Data.AF[1][indx]) == 0) { + pstRDSData->AFON_Data.Addr_Cnt = 0x0F; + pstRDSData->event_status &= (~RDS_EVENT_AFON_LIST); + } + } + } else + pstRDSData->AFON_Data.Addr_Cnt = 0x0F; + } + } + } + } + } else { + //Type B + TA_ON = block_data[1] & 0x0008; + WCN_DBG(FM_DBG | RDSC, "TA g14 typeB pstRDSData->RDSFlag.TP=%d pstRDSData->RDSFlag.TA=%d TP_ON=%d TA_ON=%d\n", pstRDSData->RDSFlag.TP, pstRDSData->RDSFlag.TA, TP_ON, TA_ON); + + if ((!pstRDSData->RDSFlag.TP) && (pstRDSData->RDSFlag.TA) && TP_ON && TA_ON) { + fm_s32 TA_num = 0; + + for (num = 0; num < 25; num++) { + if (pstRDSData->AFON_Data.AF[1][num] != 0) { + TA_num++; + } else { + break; + } + } + + WCN_DBG(FM_NTC | RDSC, "TA set RDS_EVENT_TAON"); + + if (TA_num == pstRDSData->AFON_Data.AF_Num) { + pstRDSData->event_status |= RDS_EVENT_TAON; + } + } + } + + return ret; +} + +/* + * rds_parser + * Block0: PI code(16bits) + * Block1: Group type(4bits), B0=version code(1bit), TP=traffic program code(1bit), + * PTY=program type code(5bits), other(5bits) + * Block2: 16bits + * Block3: 16bits + * @rds_dst - target buffer that record RDS parsing result + * @rds_raw - rds raw data + * @rds_size - size of rds raw data + * @getfreq - function pointer, AF need get current freq + */ +fm_s32 rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)) +{ + fm_s32 ret = 0; + //block_data[0] = blockA, block_data[1] = blockB, block_data[2] = blockC, block_data[3] = blockD, + //block_data[4] = CRC, block_data[5] = CBC + fm_u16 block_data[6]; + fm_u8 GroupType, SubType = 0; + fm_s32 rds_cnt = 0; + fm_s32 i = 0; + fm_bool dirty = fm_false; + //target buf to fill the result in + fm_u16 *event = &rds_dst->event_status; + fm_u32 *flag = &rds_dst->RDSFlag.flag_status; + + FMR_ASSERT(getfreq); + rds_get_freq = getfreq; + + ret = rds_cnt_get(rds_raw, rds_size, &rds_cnt); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get cnt err[ret=%d]\n", ret); + return ret; + } + + while (rds_cnt > 0) { + ret = rds_grp_get(&block_data[0], rds_raw, i); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get group err[ret=%d]\n", ret); + goto do_next; + } + + ret = rds_grp_type_get(block_data[4], block_data[1], &GroupType, &SubType); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get group type err[ret=%d]\n", ret); + goto do_next; + } + + ret = rds_grp_counter_add(GroupType, SubType, &rds_dst->gc); + + ret = rds_grp_pi_get(block_data[4], block_data[0], &rds_dst->PI, &dirty); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get group pi err[ret=%d]\n", ret); + goto do_next; + } else if (dirty == fm_true) { + ret = rds_event_set(event, RDS_EVENT_PI_CODE); //yes, we got new PI code + } + + ret = rds_grp_pty_get(block_data[4], block_data[1], &rds_dst->PTY, &dirty); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get group pty err[ret=%d]\n", ret); + goto do_next; + } else if (dirty == fm_true) { + ret = rds_event_set(event, RDS_EVENT_PTY_CODE); // yes, we got new PTY code + } + + ret = rds_grp_tp_get(block_data[4], block_data[1], &rds_dst->RDSFlag.TP, &dirty); + + if (ret) { + WCN_DBG(FM_WAR | RDSC, "get group tp err[ret=%d]\n", ret); + goto do_next; + } else if (dirty == fm_true) { + ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TP code + ret = rds_flag_set(flag, RDS_FLAG_IS_TP); + } + + switch (GroupType) { + case 0: + + if ((ret = rds_retrieve_g0(&block_data[0], SubType, rds_dst))) + goto do_next; + + break; + case 1: + + if ((ret = rds_retrieve_g1(&block_data[0], SubType, rds_dst))) + goto do_next; + + break; + case 2: + + if ((ret = rds_retrieve_g2(&block_data[0], SubType, rds_dst))) + goto do_next; + + break; + case 4: + + if ((ret = rds_retrieve_g4(&block_data[0], SubType, rds_dst))) + goto do_next; + + break; + case 14: + + if ((ret = rds_retrieve_g14(&block_data[0], SubType, rds_dst))) + goto do_next; + + break; + default: + break; + } + +do_next: + + if (ret && (ret != -FM_ECRC)) { + WCN_DBG(FM_ERR | RDSC, "parsing err[ret=%d]\n", ret); + return ret; + } + + rds_cnt--; + i++; + } + + return ret; +} + + diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c new file mode 100755 index 000000000000..0f52f4e9c1b2 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c @@ -0,0 +1,685 @@ +/* fm_event.c + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * FM Radio Driver -- a common event + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_utils.h" + +static fm_u32 fm_event_send(struct fm_flag_event* thiz, fm_u32 mask) +{ + thiz->flag |= mask; + //WCN_DBG(FM_DBG|MAIN, "%s set 0x%08x\n", thiz->name, thiz->flag); + wake_up((wait_queue_head_t*)(thiz->priv)); + + return thiz->flag; +} + +static fm_s32 fm_event_wait(struct fm_flag_event* thiz, fm_u32 mask) +{ + return wait_event_interruptible(*(wait_queue_head_t*)(thiz->priv), ((thiz->flag & mask) == mask)); +} + +/** + * fm_event_check - sleep until a condition gets true or a timeout elapses + * @thiz: the pointer of current object + * @mask: bitmap in fm_u32 + * @timeout: timeout, in jiffies + * + * fm_event_set() has to be called after changing any variable that could + * change the result of the wait condition. + * + * The function returns 0 if the @timeout elapsed, and the remaining + * jiffies if the condition evaluated to true before the timeout elapsed. + */ +long fm_event_wait_timeout(struct fm_flag_event* thiz, fm_u32 mask, long timeout) +{ + return wait_event_timeout(*((wait_queue_head_t*)(thiz->priv)), ((thiz->flag & mask) == mask), timeout*HZ); +} + +static fm_u32 fm_event_clr(struct fm_flag_event* thiz, fm_u32 mask) +{ + thiz->flag &= ~mask; + //WCN_DBG(FM_DBG|MAIN, "%s clr 0x%08x\n", thiz->name, thiz->flag); + return thiz->flag; +} + +static fm_u32 fm_event_get(struct fm_flag_event* thiz) +{ + return thiz->flag; + +} + +static fm_u32 fm_event_rst(struct fm_flag_event* thiz) +{ + return thiz->flag = 0; +} + +struct fm_flag_event* fm_flag_event_create(const fm_s8 *name) +{ + struct fm_flag_event *tmp; + wait_queue_head_t *wq; + + if (!(tmp = fm_zalloc(sizeof(struct fm_flag_event)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_event) -ENOMEM\n"); + return NULL; + } + + if (!(wq = fm_zalloc(sizeof(wait_queue_head_t)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(wait_queue_head_t) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + tmp->priv = wq; + init_waitqueue_head(wq); + tmp->ref = 0; + + tmp->send = fm_event_send; + tmp->wait = fm_event_wait; + tmp->wait_timeout = fm_event_wait_timeout; + tmp->clr = fm_event_clr; + tmp->get = fm_event_get; + tmp->rst = fm_event_rst; + + tmp->rst(tmp); //set flag to 0x00000000 + + return tmp; +} + +fm_s32 fm_flag_event_get(struct fm_flag_event *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_flag_event_put(struct fm_flag_event *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + fm_free(thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + +//fm lock methods +static fm_s32 fm_lock_try(struct fm_lock *thiz,fm_s32 retryCnt) +{ + fm_s32 retry_cnt = 0; + struct semaphore *sem; + struct task_struct *task = current; + FMR_ASSERT(thiz); + FMR_ASSERT(thiz->priv); + + while(down_trylock((struct semaphore*)thiz->priv)) + { + WCN_DBG(FM_WAR | MAIN, "down_trylock failed\n"); + if(++retry_cnt < retryCnt) + { + WCN_DBG(FM_WAR | MAIN,"[retryCnt=%d]\n", retry_cnt); + msleep_interruptible(50); + continue; + } + else + { + WCN_DBG(FM_CRT | MAIN,"down_trylock retry failed\n"); + return -FM_ELOCK; + } + } + + sem = (struct semaphore*)thiz->priv; + WCN_DBG(FM_NTC | MAIN, "%s --->trylock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid); + return 0; +} + +//fm try lock methods +static fm_s32 fm_lock_lock(struct fm_lock *thiz) +{ + struct semaphore *sem; + struct task_struct *task = current; + FMR_ASSERT(thiz); + FMR_ASSERT(thiz->priv); + + if (down_interruptible((struct semaphore*)thiz->priv)) { + WCN_DBG(FM_CRT | MAIN, "get mutex failed\n"); + return -FM_ELOCK; + } + + sem = (struct semaphore*)thiz->priv; + WCN_DBG(FM_NTC | MAIN, "%s --->lock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid); + return 0; +} + +static fm_s32 fm_lock_unlock(struct fm_lock *thiz) +{ + struct semaphore *sem; + struct task_struct *task = current; + FMR_ASSERT(thiz); + FMR_ASSERT(thiz->priv); + sem = (struct semaphore*)thiz->priv; + WCN_DBG(FM_NTC | MAIN, "%s <---unlock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count + 1, task->pid); + up((struct semaphore*)thiz->priv); + return 0; +} + +struct fm_lock* fm_lock_create(const fm_s8 *name) +{ + struct fm_lock *tmp; + struct semaphore *mutex; + + if (!(tmp = fm_zalloc(sizeof(struct fm_lock)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n"); + return NULL; + } + + if (!(mutex = fm_zalloc(sizeof(struct semaphore)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct semaphore) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + tmp->priv = mutex; + sema_init(mutex, 1); + tmp->ref = 0; + fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + + tmp->lock = fm_lock_lock; + tmp->trylock = fm_lock_try; + tmp->unlock = fm_lock_unlock; + + return tmp; +} + +fm_s32 fm_lock_get(struct fm_lock *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_lock_put(struct fm_lock *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + fm_free(thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + +//fm lock methods +static fm_s32 fm_spin_lock_lock(struct fm_lock *thiz) +{ + struct task_struct *task = current; + FMR_ASSERT(thiz); + FMR_ASSERT(thiz->priv); + + spin_lock_bh((spinlock_t *)thiz->priv); + + WCN_DBG(FM_NTC | MAIN, "%s --->lock pid=%d\n", thiz->name, task->pid); + return 0; +} + +static fm_s32 fm_spin_lock_unlock(struct fm_lock *thiz) +{ + struct task_struct *task = current; + FMR_ASSERT(thiz); + FMR_ASSERT(thiz->priv); + + WCN_DBG(FM_NTC | MAIN, "%s <---unlock, pid=%d\n", thiz->name, task->pid); + spin_unlock_bh((spinlock_t *)thiz->priv); + return 0; +} + +struct fm_lock* fm_spin_lock_create(const fm_s8 *name) +{ + struct fm_lock *tmp; + spinlock_t *spin_lock; + + if (!(tmp = fm_zalloc(sizeof(struct fm_lock)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n"); + return NULL; + } + + if (!(spin_lock = fm_zalloc(sizeof(spinlock_t)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(spinlock_t) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + tmp->priv = spin_lock; + spin_lock_init(spin_lock); + tmp->ref = 0; + fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + + tmp->lock = fm_spin_lock_lock; + tmp->unlock = fm_spin_lock_unlock; + + return tmp; +} + + +fm_s32 fm_spin_lock_get(struct fm_lock *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_spin_lock_put(struct fm_lock *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + fm_free(thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + +/* + * fm timer + * + */ +static fm_s32 fm_timer_init(struct fm_timer *thiz, void (*timeout)(unsigned long data), unsigned long data, signed long time, fm_s32 flag) +{ + struct timer_list *timerlist = (struct timer_list*)thiz->priv; + + thiz->flag = flag; + thiz->flag &= ~FM_TIMER_FLAG_ACTIVATED; + thiz->timeout_func = timeout; + thiz->data = data; + thiz->timeout_ms = time; + + timerlist->expires = jiffies + (thiz->timeout_ms) / (1000 / HZ); + timerlist->function = thiz->timeout_func; + timerlist->data = (unsigned long)thiz->data; + + return 0; +} + +static fm_s32 fm_timer_start(struct fm_timer *thiz) +{ + struct timer_list *timerlist = (struct timer_list*)thiz->priv; + + thiz->flag |= FM_TIMER_FLAG_ACTIVATED; + mod_timer(timerlist, jiffies + (thiz->timeout_ms) / (1000 / HZ)); + + return 0; +} + +static fm_s32 fm_timer_update(struct fm_timer *thiz) +{ + struct timer_list *timerlist = (struct timer_list*)thiz->priv; + + if (thiz->flag & FM_TIMER_FLAG_ACTIVATED) { + mod_timer(timerlist, jiffies + (thiz->timeout_ms) / (1000 / HZ)); + return 0; + } else { + return 1; + } +} + +static fm_s32 fm_timer_stop(struct fm_timer *thiz) +{ + struct timer_list *timerlist = (struct timer_list*)thiz->priv; + + thiz->flag &= ~FM_TIMER_FLAG_ACTIVATED; + del_timer(timerlist); + + return 0; +} + +static fm_s32 fm_timer_control(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void* arg) +{ + + return 0; +} + +struct fm_timer* fm_timer_create(const fm_s8 *name) +{ + struct fm_timer *tmp; + struct timer_list *timerlist; + + if (!(tmp = fm_zalloc(sizeof(struct fm_timer)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_timer) -ENOMEM\n"); + return NULL; + } + + if (!(timerlist = fm_zalloc(sizeof(struct timer_list)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct timer_list) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + init_timer(timerlist); + + fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + tmp->priv = timerlist; + tmp->ref = 0; + tmp->init = fm_timer_init; + tmp->start = fm_timer_start; + tmp->stop = fm_timer_stop; + tmp->update = fm_timer_update; + tmp->control = fm_timer_control; + + return tmp; +} + +fm_s32 fm_timer_get(struct fm_timer *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_timer_put(struct fm_timer *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + fm_free(thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + + +/* + * FM work thread mechanism + */ +static fm_s32 fm_work_init(struct fm_work *thiz, void (*work_func)(unsigned long data), unsigned long data) +{ + struct work_struct *sys_work = (struct work_struct*)thiz->priv; + work_func_t func; + + thiz->work_func = work_func; + thiz->data = data; + func = (work_func_t)thiz->work_func; + + INIT_WORK(sys_work, func); + + return 0; + +} + +struct fm_work* fm_work_create(const fm_s8 *name) +{ + struct fm_work *my_work; + struct work_struct *sys_work; + + if (!(my_work = fm_zalloc(sizeof(struct fm_work)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_work) -ENOMEM\n"); + return NULL; + } + + if (!(sys_work = fm_zalloc(sizeof(struct work_struct)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct work_struct) -ENOMEM\n"); + fm_free(my_work); + return NULL; + } + + fm_memcpy(my_work->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + my_work->priv = sys_work; + my_work->init = fm_work_init; + + return my_work; +} + +fm_s32 fm_work_get(struct fm_work *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_work_put(struct fm_work *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + fm_free(thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + + +static fm_s32 fm_workthread_add_work(struct fm_workthread *thiz, struct fm_work *work) +{ + FMR_ASSERT(thiz); + FMR_ASSERT(work); + + queue_work((struct workqueue_struct*)thiz->priv, (struct work_struct*)work->priv); + return 0; +} + +struct fm_workthread* fm_workthread_create(const fm_s8* name) +{ + struct fm_workthread *my_thread; + struct workqueue_struct *sys_thread; + + if (!(my_thread = fm_zalloc(sizeof(struct fm_workthread)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_workthread) -ENOMEM\n"); + return NULL; + } + + sys_thread = create_singlethread_workqueue(name); + + fm_memcpy(my_thread->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name))); + my_thread->priv = sys_thread; + my_thread->add_work = fm_workthread_add_work; + + return my_thread; +} + +fm_s32 fm_workthread_get(struct fm_workthread *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref++; + return 0; +} + +fm_s32 fm_workthread_put(struct fm_workthread *thiz) +{ + FMR_ASSERT(thiz); + thiz->ref--; + + if (thiz->ref == 0) { + destroy_workqueue((struct workqueue_struct*)thiz->priv); + fm_free(thiz); + return 0; + } else if (thiz->ref > 0) { + return -FM_EINUSE; + } else { + return -FM_EPARA; + } +} + + +fm_s32 fm_fifo_in(struct fm_fifo *thiz, void *item) +{ + FMR_ASSERT(item); + + if (thiz->len < thiz->size) { + fm_memcpy((thiz->obj.priv + (thiz->item_size * thiz->in)), item, thiz->item_size); + thiz->in = (thiz->in + 1) % thiz->size; + thiz->len++; + //WCN_DBG(FM_DBG | MAIN, "add a new item[len=%d]\n", thiz->len); + } else { + WCN_DBG(FM_WAR | MAIN, "%s fifo is full\n", thiz->obj.name); + return -FM_ENOMEM; + } + + return 0; +} + +fm_s32 fm_fifo_out(struct fm_fifo *thiz, void *item) +{ + if (thiz->len > 0) { + if (item) { + fm_memcpy(item, (thiz->obj.priv + (thiz->item_size * thiz->out)), thiz->item_size); + fm_memset((thiz->obj.priv + (thiz->item_size * thiz->out)), 0, thiz->item_size); + } + thiz->out = (thiz->out + 1) % thiz->size; + thiz->len--; + //WCN_DBG(FM_DBG | MAIN, "del an item[len=%d]\n", thiz->len); + } else { + WCN_DBG(FM_WAR | MAIN, "%s fifo is empty\n", thiz->obj.name); + } + + return 0; +} + +fm_bool fm_fifo_is_full(struct fm_fifo *thiz) +{ + return (thiz->len == thiz->size) ? fm_true : fm_false; +} + +fm_bool fm_fifo_is_empty(struct fm_fifo *thiz) +{ + return (thiz->len == 0) ? fm_true : fm_false; +} + +fm_s32 fm_fifo_get_total_len(struct fm_fifo *thiz) +{ + return thiz->size; +} + +fm_s32 fm_fifo_get_valid_len(struct fm_fifo *thiz) +{ + return thiz->len; +} + +fm_s32 fm_fifo_reset(struct fm_fifo *thiz) +{ + fm_memset(thiz->obj.priv, 0, thiz->item_size * thiz->size); + thiz->in = 0; + thiz->out = 0; + thiz->len = 0; + + return 0; +} + +struct fm_fifo* fm_fifo_init(struct fm_fifo* fifo, void *buf, const fm_s8 *name, fm_s32 item_size, fm_s32 item_num) +{ + fm_memcpy(fifo->obj.name, name, 20); + fifo->size = item_num; + fifo->in = 0; + fifo->out = 0; + fifo->len = 0; + fifo->item_size = item_size; + fifo->obj.priv = buf; + + fifo->input = fm_fifo_in; + fifo->output = fm_fifo_out; + fifo->is_full = fm_fifo_is_full; + fifo->is_empty = fm_fifo_is_empty; + fifo->get_total_len = fm_fifo_get_total_len; + fifo->get_valid_len = fm_fifo_get_valid_len; + fifo->reset = fm_fifo_reset; + + WCN_DBG(FM_NTC | LINK, "%s inited\n", fifo->obj.name); + + return fifo; +} + +struct fm_fifo* fm_fifo_create(const fm_s8 *name, fm_s32 item_size, fm_s32 item_num) +{ + struct fm_fifo *tmp; + void *buf; + + if (!(tmp = fm_zalloc(sizeof(struct fm_fifo)))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_fifo) -ENOMEM\n"); + return NULL; + } + + if (!(buf = fm_zalloc(item_size * item_num))) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_fifo) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + tmp = fm_fifo_init(tmp, buf, name, item_size, item_num); + + WCN_DBG(FM_NTC | LINK, "%s created\n", tmp->obj.name); + + return tmp; +} + + +fm_s32 fm_fifo_release(struct fm_fifo *fifo) +{ + if (fifo) { + WCN_DBG(FM_NTC | LINK, "%s released\n", fifo->obj.name); + if (fifo->obj.priv) { + fm_free(fifo->obj.priv); + } + fm_free(fifo); + } + + return 0; +} + + + diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h new file mode 100755 index 000000000000..8ff7d1994f79 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h @@ -0,0 +1,133 @@ +/* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/arch/arm/mach-mt6516/include/mach/fm.h + * + * (C) Copyright 2009 + * MediaTek + * William Chung + * + * MT6516 AR10x0 FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FM_CUST_CFG_H__ +#define __FM_CUST_CFG_H__ + +//scan sort algorithm +enum { + FM_SCAN_SORT_NON = 0, + FM_SCAN_SORT_UP, + FM_SCAN_SORT_DOWN, + FM_SCAN_SORT_MAX +}; +//***********************************FM config for customer *********************************** +//RX +#define FMR_RSSI_TH_LONG_MT6620 0x0301 //FM radio long antenna RSSI threshold(11.375dBuV) +#define FMR_RSSI_TH_SHORT_MT6620 0x02E0 //FM radio short antenna RSSI threshold(-1dBuV) +#define FMR_CQI_TH_MT6620 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +//***********************************FM config for engineer *********************************** +//RX +#define FMR_MR_TH_MT6620 0x01BD //FM radio MR threshold +#if 0 +//***************************************************************************************** +//***********************************FM config for customer *********************************** +//***************************************************************************************** +#define FMR_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define FMR_SCAN_CH_SIZE 40 //FM radio scan max channel size +#define FMR_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +#define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON +#define FM_FAKE_CH_NUM 1 +#define FM_FAKE_CH_RSSI 40 +#define FM_FAKE_CH_1 1075 +#define FM_FAKE_CH_2 0 +#define FM_FAKE_CH_3 0 +#define FM_FAKE_CH_4 0 +#define FM_FAKE_CH_5 0 + +//TX +#define FMTX_PWR_LEVEL_MAX 120 + +//***************************************************************************************** +#define ADDR_SCAN_TH 0xE0 //scan thrshold register +#define ADDR_CQI_TH 0xE1 //scan CQI register + +//TX +#define FMTX_SCAN_HOLE_LOW 923 //92.3MHz~95.4MHz should not show to user +#define FMTX_SCAN_HOLE_HIGH 954 //92.3MHz~95.4MHz should not show to user +//***************************************************************************************** + +// errno +#define FM_SUCCESS 0 +#define FM_FAILED 1 +#define FM_EPARM 2 +#define FM_BADSTATUS 3 +#define FM_TUNE_FAILED 4 +#define FM_SEEK_FAILED 5 +#define FM_BUSY 6 +#define FM_SCAN_FAILED 7 + +//max scan chl num +#define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE +// auto HiLo +#define FM_AUTO_HILO_OFF 0 +#define FM_AUTO_HILO_ON 1 + +#define FM_CHIP_AR1000 0x1000 +#define FM_CHIP_MT5192 0x91 +#define FM_CHIP_MT5193 0x92 +#define FM_CHIP_MT6616 0x6616 +#define FM_CHIP_MT6626 0x6626 +#define FM_CHIP_MT6628 0x6628 +#define FM_CHIP_MT6620 0x6620 +#define FM_CHIP_UNSUPPORTED 0xffff + +// seek threshold +#define FM_SEEKTH_LEVEL_DEFAULT 4 +#endif +//RX +#define FM_RX_RSSI_TH_LONG_MT6620 -296 //FM radio long antenna RSSI threshold(-4dBuV) +#define FM_RX_RSSI_TH_SHORT_MT6620 -296 //FM radio short antenna RSSI threshold(-4dBuV) +#define FM_RX_DESENSE_RSSI_MT6620 -245 +#define FM_RX_PAMD_TH_MT6620 -12 +#define FM_RX_MR_TH_MT6620 -67 +#define FM_RX_ATDC_TH_MT6620 219 +#define FM_RX_PRX_TH_MT6620 64 +#define FM_RX_SMG_TH_MT6620 6 //FM soft-mute gain threshold +#define FM_RX_DEEMPHASIS_MT6620 0 //0-50us, China Mainland; 1-75us China Taiwan +#define FM_RX_OSC_FREQ_MT6620 0 //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz +#if 0 +#define FM_RX_RSSI_TH_LONG_MT6620 0xF2D8 //FM radio long antenna RSSI threshold(-4dBuV) +#define FM_RX_RSSI_TH_SHORT_MT6620 0xF2D8 //FM radio short antenna RSSI threshold(-4dBuV) +#define FM_RX_CQI_TH_MT6620 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +#define FM_RX_MR_TH_MT6620 0x01BD //FM radio MR threshold +#define FM_RX_SMG_TH_MT6620 0x4025 //FM soft-mute gain threshold +#define FM_RX_SEEK_SPACE_MT6620 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define FM_RX_SCAN_CH_SIZE_MT6620 40 //FM radio scan max channel size +#define FM_RX_BAND_MT6620 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special + +#define FM_RX_SCAN_SORT_SELECT_MT6620 FM_SCAN_SORT_NON +#define FM_RX_FAKE_CH_NUM_MT6620 1 +#define FM_RX_FAKE_CH_RSSI_MT6620 40 +#define FM_RX_FAKE_CH_1_MT6620 1075 +#define FM_RX_FAKE_CH_2_MT6620 0 +#define FM_RX_FAKE_CH_3_MT6620 0 +#define FM_RX_FAKE_CH_4_MT6620 0 +#define FM_RX_FAKE_CH_5_MT6620 0 +#endif +//TX +#define FM_TX_PWR_LEVEL_MAX_MT6620 120 +#define FM_TX_SCAN_HOLE_LOW_MT6620 923 //92.3MHz~95.4MHz should not show to user +#define FM_TX_SCAN_HOLE_HIGH_MT6620 954 //92.3MHz~95.4MHz should not show to user + +#endif // __FM_CUST_CFG_H__ diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h new file mode 100755 index 000000000000..6637042027d4 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h @@ -0,0 +1,105 @@ +/* + * + * (C) Copyright 20011 + * MediaTek + * Hongcheng Xia + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FM_CUST_CFG_H__ +#define __FM_CUST_CFG_H__ + +//scan sort algorithm +enum{ + FM_SCAN_SORT_NON = 0, + FM_SCAN_SORT_UP, + FM_SCAN_SORT_DOWN, + FM_SCAN_SORT_MAX +}; + +//***************************************************************************************** +//***********************************FM config for customer: start****************************** +//***************************************************************************************** +//RX +#define FM_RX_RSSI_TH_LONG 0xFF01 //FM radio long antenna RSSI threshold(11.375dBuV) +#define FM_RX_RSSI_TH_SHORT 0xFEE0 //FM radio short antenna RSSI threshold(-1dBuV) +#define FM_RX_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +#define FM_RX_MR_TH 0x01BD //FM radio MR threshold +#define FM_RX_SMG_TH 0x4025 //FM soft-mute gain threshold +#define FM_RX_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define FM_RX_SCAN_CH_SIZE 40 //FM radio scan max channel size +#define FM_RX_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +#define FM_RX_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) +#define FM_RX_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) +#define FM_RX_SCAN_SORT_SELECT FM_SCAN_SORT_NON +#define FM_RX_FAKE_CH_NUM 1 +#define FM_RX_FAKE_CH_RSSI 40 +#define FM_RX_FAKE_CH_1 1075 +#define FM_RX_FAKE_CH_2 0 +#define FM_RX_FAKE_CH_3 0 +#define FM_RX_FAKE_CH_4 0 +#define FM_RX_FAKE_CH_5 0 +#define FM_RX_DEEMPHASIS 0 //0-50us, China Mainland; 1-75us China Taiwan +#define FM_RX_OSC_FREQ 0 //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz + +//TX +#define FM_TX_PWR_LEVEL_MAX 120 +#define FM_TX_SCAN_HOLE_LOW 923 //92.3MHz~95.4MHz should not show to user +#define FM_TX_SCAN_HOLE_HIGH 954 //92.3MHz~95.4MHz should not show to user + + +//***************************************************************************************** +//***********************************FM config for customer:end ******************************* +//***************************************************************************************** +// band +#define FM_BAND_UNKNOWN 0 +#define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT) +#define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz +#define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz +#define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz +#define FM_BAND_DEFAULT FM_BAND_UE +#define FM_FREQ_MIN FM_RX_BAND_FREQ_L +#define FM_FREQ_MAX FM_RX_BAND_FREQ_H +#define FM_RAIDO_BAND FM_BAND_UE +// space +#define FM_SPACE_UNKNOWN 0 +#define FM_SPACE_100K 1 +#define FM_SPACE_200K 2 +#define FM_SPACE_DEFAULT FM_RX_SEEK_SPACE +#define FM_SEEK_SPACE FM_RX_SEEK_SPACE +//max scan chl num +#define FM_MAX_CHL_SIZE FM_RX_SCAN_CH_SIZE +// auto HiLo +#define FM_AUTO_HILO_OFF 0 +#define FM_AUTO_HILO_ON 1 +// seek direction +#define FM_SEEK_UP 0 +#define FM_SEEK_DOWN 1 + +#define FM_CHIP_AR1000 0x1000 +#define FM_CHIP_MT5192 0x91 +#define FM_CHIP_MT5193 0x92 +#define FM_CHIP_MT6616 0x6616 +#define FM_CHIP_MT6626 0x6626 +#define FM_CHIP_MT6628 0x6628 +#define FM_CHIP_MT6620 0x6620 +#define FM_CHIP_UNSUPPORTED 0xffff + +// seek threshold +#define FM_SEEKTH_LEVEL_DEFAULT 4 +#endif // __FM_CUST_CFG_H__ \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h new file mode 100755 index 000000000000..e90f3c37ba51 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h @@ -0,0 +1,99 @@ +/* + * + * (C) Copyright 20011 + * MediaTek + * Hongcheng Xia + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FM_CUST_CFG_H__ +#define __FM_CUST_CFG_H__ + +//scan sort algorithm +enum{ + FM_SCAN_SORT_NON = 0, + FM_SCAN_SORT_UP, + FM_SCAN_SORT_DOWN, + FM_SCAN_SORT_MAX +}; +/*typedef struct { + fm_s32 short_ana_rssi_th; + fm_s32 long_ana_rssi_th; + fm_s32 desene_rssi_th; + fm_s32 pamd_th; + fm_s32 mr_th; + fm_s32 atdc_th; + fm_u32 prx_th; + fm_u32 atdev_th; + fm_u16 smg_th; + fm_u16 deemphasis; + fm_u16 osc_freq; +}mt6628_fm_rx_cust_cfg; + +typedef struct{ + mt6628_fm_rx_cust_cfg rx_cfg; +}mt6628_fm_cust_cfg; +*/ +//***************************************************************************************** +//***********************************FM config for customer: start****************************** +//***************************************************************************************** +//RX +#define FM_RX_RSSI_TH_LONG_MT6628 -296 //FM radio long antenna RSSI threshold(-4dBuV) +#define FM_RX_RSSI_TH_SHORT_MT6628 -296 //FM radio short antenna RSSI threshold(-4dBuV) +#define FM_RX_DESENSE_RSSI_MT6628 -258 +#define FM_RX_PAMD_TH_MT6628 -12 +#define FM_RX_MR_TH_MT6628 -67 +#define FM_RX_ATDC_TH_MT6628 3496 +#define FM_RX_PRX_TH_MT6628 64 +#define FM_RX_SMG_TH_MT6628 16421 //FM soft-mute gain threshold +#define FM_RX_DEEMPHASIS_MT6628 0 //0-50us, China Mainland; 1-75us China Taiwan +#define FM_RX_OSC_FREQ_MT6628 0 //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz +//#define FM_RX_SEEK_SPACE_MT6628 1 //FM radio seek space,1:100KHZ; 2:200KHZ +//#define FM_RX_SCAN_CH_SIZE_MT6628 40 //FM radio scan max channel size +//#define FM_RX_BAND_MT6628 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +//#define FM_RX_SCAN_SORT_SELECT_MT6628 FM_SCAN_SORT_NON +//#define FM_RX_FAKE_CH_NUM_MT6628 1 +//#define FM_RX_FAKE_CH_RSSI_MT6628 40 +//#define FM_RX_FAKE_CH_1_MT6628 1075 +//#define FM_RX_FAKE_CH_2_MT6628 0 +//#define FM_RX_FAKE_CH_3_MT6628 0 +//#define FM_RX_FAKE_CH_4_MT6628 0 +//#define FM_RX_FAKE_CH_5_MT6628 0 + +//TX +//#define FM_TX_PWR_LEVEL_MAX_MT6628 120 +//#define FM_TX_SCAN_HOLE_LOW_MT6628 923 //92.3MHz~95.4MHz should not show to user +//#define FM_TX_SCAN_HOLE_HIGH_MT6628 954 //92.3MHz~95.4MHz should not show to user + + +//***************************************************************************************** +//***********************************FM config for customer:end ******************************* +//***************************************************************************************** + +//#define FM_SEEK_SPACE_MT6628 FM_RX_SEEK_SPACE_MT6628 +//max scan chl num +//#define FM_MAX_CHL_SIZ_MT6628E FM_RX_SCAN_CH_SIZE_MT6628 +// auto HiLo +#define FM_AUTO_HILO_OFF_MT6628 0 +#define FM_AUTO_HILO_ON_MT6628 1 + + +// seek threshold +#define FM_SEEKTH_LEVEL_DEFAULT_MT6628 4 + +#endif // __FM_CUST_CFG_H__ diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h new file mode 100755 index 000000000000..ec796674d9db --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h @@ -0,0 +1,200 @@ +/* fm_config.h + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FM_CONFIG_H__ +#define __FM_CONFIG_H__ + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +// band +#define FM_BAND_UNKNOWN 0 +#define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT) +#define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz +#define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz +#define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz +#define FM_BAND_DEFAULT FM_BAND_UE +#define FM_RAIDO_BAND FM_BAND_UE +#define FM_FREQ_MIN FM_RX_BAND_FREQ_L +#define FM_FREQ_MAX FM_RX_BAND_FREQ_H + +#ifdef MTK_FM_50KHZ_SUPPORT +#define FM_UE_FREQ_MIN 8750 +#define FM_UE_FREQ_MAX 10800 +#define FM_JP_FREQ_MIN 7600 +#define FM_JP_FREQ_MAX 10800 + +#define FM_RX_BAND_FREQ_L 8750 //FM radio special band low freq(Default 87.5MHz) +#define FM_RX_BAND_FREQ_H 10800 //FM radio special band high freq(Default 108.0MHz) +//TX +#define FM_TX_SCAN_HOLE_LOW 9230 //92.3MHz~95.4MHz should not show to user +#define FM_TX_SCAN_HOLE_HIGH 9540 //92.3MHz~95.4MHz should not show to user + +#else +#define FM_UE_FREQ_MIN 875 +#define FM_UE_FREQ_MAX 1080 +#define FM_JP_FREQ_MIN 760 +#define FM_JP_FREQ_MAX 1080 + +#define FM_RX_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) +#define FM_RX_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) +//TX +#define FM_TX_SCAN_HOLE_LOW 923 //92.30MHz~95.40MHz should not show to user +#define FM_TX_SCAN_HOLE_HIGH 954 //92.30MHz~95.40MHz should not show to user + +#endif //MTK_FM_50KHZ_SUPPORT + +// space +#define FM_SPACE_UNKNOWN 0 +#define FM_SPACE_100K 1 +#define FM_SPACE_200K 2 +#define FM_SPACE_50K 5 + +#ifdef MTK_FM_50KHZ_SUPPORT +#define FM_SPACE_DEFAULT FM_SPACE_50K +#else +#define FM_SPACE_DEFAULT FM_SPACE_100K +#endif + +#define FM_TX_SCAN_UP (0) +#define FM_TX_SCAN_DOWN (1) +#define FM_TX_SCAN_MAX 10 +#define FM_TX_SCAN_MIN 1 + +// seek direction +#define FM_SEEK_UP 0 +#define FM_SEEK_DOWN 1 + +#define FM_CHIP_AR1000 0x1000 +#define FM_CHIP_MT5192 0x91 +#define FM_CHIP_MT5193 0x92 +#define FM_CHIP_MT6616 0x6616 +#define FM_CHIP_MT6626 0x6626 +#define FM_CHIP_MT6628 0x6628 +#define FM_CHIP_MT6620 0x6620 +#define FM_CHIP_UNSUPPORTED 0xffff + +enum fm_cfg_parser_state { + FM_CFG_STAT_NONE = 0, + FM_CFG_STAT_GROUP, + FM_CFG_STAT_KEY, + FM_CFG_STAT_VALUE, + FM_CFG_STAT_COMMENT +}; + +typedef enum fm_cfg_parser_state fm_cfg_parser_state_t; + +#define COMMENT_CHAR '#' +#define DELIMIT_CHAR '=' + +#define isspace(a) ((a) == 0x20) + +#define FAKE_CH_MAX 10 +#define FM_CUST_CFG_PATH "/etc/fm_cust.cfg" + +struct fm_rx_cust_cfg { + fm_s32 desene_rssi_th; + fm_s32 pamd_th; + fm_s32 mr_th; + fm_s32 atdc_th; + fm_s32 prx_th; + fm_s32 atdev_th; + fm_s32 short_ana_rssi_th; + fm_s32 long_ana_rssi_th; + fm_s32 cqi_th; +// fm_u16 mr_th; + fm_s32 smg_th; + fm_s32 scan_ch_size; + fm_s32 seek_space; + fm_s32 band; + fm_s32 band_freq_l; + fm_s32 band_freq_h; + fm_s32 scan_sort; + fm_s32 fake_ch[FAKE_CH_MAX]; + fm_s32 fake_ch_num; + fm_s32 fake_ch_rssi_th; + fm_s32 deemphasis; + fm_s32 osc_freq; +}; + +struct fm_tx_cust_cfg { + fm_s32 scan_hole_low; + fm_s32 scan_hole_high; + fm_s32 power_level; +}; + +typedef struct{ + struct fm_rx_cust_cfg rx_cfg; + struct fm_tx_cust_cfg tx_cfg; +}fm_cust_cfg; + +enum fm_cust_cfg_op { + FM_CFG_RX_RSSI_TH_LONG = 0, + FM_CFG_RX_RSSI_TH_SHORT, + FM_CFG_RX_CQI_TH, + FM_CFG_RX_MR_TH, + FM_CFG_RX_SMG_TH, + FM_CFG_RX_SCAN_CH_SIZE, + FM_CFG_RX_SEEK_SPACE, + FM_CFG_RX_BAND, + FM_CFG_RX_BAND_FREQ_L, + FM_CFG_RX_BAND_FREQ_H, + FM_CFG_RX_SCAN_SORT, + FM_CFG_RX_FAKE_CH_NUM, + FM_CFG_RX_FAKE_CH_RSSI, + FM_CFG_RX_FAKE_CH, + FM_CFG_RX_DEEMPHASIS, + FM_CFG_RX_OSC_FREQ, + + FM_CFG_TX_SCAN_HOLE_LOW, + FM_CFG_TX_SCAN_HOLE_HIGH, + FM_CFG_TX_PWR_LEVEL, + FM_CFG_MAX +}; + +typedef fm_s32(*CFG_HANDLER)(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg); +extern fm_s32 to_upper_n(fm_s8 *str, fm_s32 len); +extern fm_s32 check_hex_str(fm_s8 *str, fm_s32 len); +extern fm_s32 check_dec_str(fm_s8 *str, fm_s32 len); +extern fm_s32 ascii_to_hex(fm_s8 *in_ascii, fm_u16 *out_hex); +extern fm_s32 ascii_to_dec(fm_s8 *in_ascii, fm_s32 *out_dec); +extern fm_s32 trim_string(fm_s8 **start); +extern fm_s32 trim_path(fm_s8 **start); +extern fm_s32 cfg_parser(fm_s8 *buffer, CFG_HANDLER handler, fm_cust_cfg *cfg); +extern fm_s32 cfg_item_match(fm_s8 *src_key, fm_s8 *src_val, fm_s8 *dst_key, fm_s32 *dst_val); + +extern fm_s32 fm_cust_config(const fm_s8 *filepath); +extern fm_u16 fm_cust_config_fetch(enum fm_cust_cfg_op op_code); +#ifdef MT6628_FM +extern fm_s32 MT6628fm_cust_config_setup(const fm_s8 *filepath); +extern fm_u16 MT6628fm_cust_config_fetch(enum fm_cust_cfg_op op_code); +#endif +#ifdef MT6620_FM +extern fm_s32 MT6620fm_cust_config_setup(const fm_s8 *filepath); +extern fm_u16 MT6620fm_cust_config_fetch(enum fm_cust_cfg_op op_code); +#endif +#endif //__FM_CONFIG_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h new file mode 100755 index 000000000000..16d41b777fae --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h @@ -0,0 +1,57 @@ +#ifndef __FM_DBG_H__ +#define __FM_DBG_H__ + +#include //for printk() + +//DBG zone +#define BASE 4 +#define MAIN (1 << (BASE+0)) +#define LINK (1 << (BASE+1)) +#define EINT (1 << (BASE+2)) +#define CHIP (1 << (BASE+3)) +#define RDSC (1 << (BASE+4)) +#define G0 (1 << (BASE+5)) +#define G1 (1 << (BASE+6)) +#define G2 (1 << (BASE+7)) +#define G3 (1 << (BASE+8)) +#define G4 (1 << (BASE+9)) +#define G14 (1 << (BASE+10)) +#define RAW (1 << (BASE+11)) +#define OPEN (1 << (BASE+12)) +#define IOCTL (1 << (BASE+13)) +#define READ_ (1 << (BASE+14)) +#define CLOSE (1 << (BASE+15)) +#define CQI (1 << (BASE+16)) +#define ALL 0xfffffff0 + +//DBG level +#define L0 0x00000000 // EMERG, system will crush +#define L1 0x00000001 // ALERT, need action in time +#define L2 0x00000002 // CRIT, important HW or SW operation failed +#define L3 0x00000003 // ERR, normal HW or SW ERR +#define L4 0x00000004 // WARNING, importan path or somewhere may occurs err +#define L5 0x00000005 // NOTICE, normal case +#define L6 0x00000006 // INFO, print info if need +#define L7 0x00000007 // DEBUG, for debug info + +#define FM_EMG L0 +#define FM_ALT L1 +#define FM_CRT L2 +#define FM_ERR L3 +#define FM_WAR L4 +#define FM_NTC L5 +#define FM_INF L6 +#define FM_DBG L7 + +extern fm_u32 g_dbg_level; +#define WCN_DBG(flag, fmt, args...) \ + do { \ + if ((((flag)&0x0000000f)<=(g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + printk(KERN_ALERT "[" #flag "]" fmt, ## args); \ + } \ + } while(0) + + + +#endif //__FM_DBG_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h new file mode 100755 index 000000000000..9ce420a12821 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h @@ -0,0 +1,18 @@ +#ifndef __FM_EINT_H__ +#define __FM_EINT_H__ + +#include "fm_typedef.h" + +enum{ + FM_EINT_PIN_EINT_MODE, + FM_EINT_PIN_GPIO_MODE, + FM_EINT_PIN_MAX_MODE +}; + +extern fm_s32 fm_enable_eint(void); +extern fm_s32 fm_disable_eint(void); +extern fm_s32 fm_request_eint(void (*parser)(void)); +extern fm_s32 fm_eint_pin_cfg(fm_s32 mode); + +#endif //__FM_EINT_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h new file mode 100755 index 000000000000..c5f31d493ddf --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h @@ -0,0 +1,31 @@ +#ifndef __FM_ERR_H__ +#define __FM_ERR_H__ + +#include //for printk() + +#define FM_ERR_BASE 1000 +typedef enum fm_drv_err_t { + FM_EOK = FM_ERR_BASE, + FM_EBUF, + FM_EPARA, + FM_ELINK, + FM_ELOCK, + FM_EFW, + FM_ECRC, + FM_EWRST, //wholechip reset + FM_ESRST, //subsystem reset + FM_EPATCH, + FM_ENOMEM, + FM_EINUSE, //other client is using this object + FM_EMAX +} fm_drv_err_t; + +#define FMR_ASSERT(a) { \ + if ((a) == NULL) { \ + printk("%s,invalid pointer\n", __func__);\ + return -FM_EPARA; \ + } \ + } + +#endif //__FM_ERR_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h new file mode 100755 index 000000000000..5a5daa8a1b2a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h @@ -0,0 +1,222 @@ +#ifndef __FM_INTERFACE_H__ +#define __FM_INTERFACE_H__ + +#include +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_utils.h" + +/****************************************************************************** + * STRUCTURE DEFINITIONS + *****************************************************************************/ +enum fm_op_state { + FM_STA_STOP = 0, + FM_STA_PLAY = 1, + FM_STA_TUNE = 2, + FM_STA_SEEK = 3, + FM_STA_SCAN = 4, + FM_STA_RAMPDOWN = 5, + FM_STA_UNKOWN = 100, + FM_STA_MAX +}; + +enum fm_pwr_state { + FM_PWR_OFF = 0, + FM_PWR_RX_ON = 1, + FM_PWR_TX_ON = 2, + FM_PWR_MAX +}; + +enum fm_audio_path { + FM_AUD_ANALOG = 0, //analog: line in + FM_AUD_DIGITAL = 1, //digital: I2S + FM_AUD_MAX +}; + +enum fm_antenna_type { + FM_ANA_LONG = 0, //long antenna + FM_ANA_SHORT = 1, //short antenna + FM_ANA_MAX +}; + +struct fm_hw_info { + fm_s32 chip_id; //chip ID, eg. 6620 + fm_s32 eco_ver; //chip ECO version, eg. E3 + fm_s32 rom_ver; //FM DSP rom code version, eg. V2 + fm_s32 patch_ver; //FM DSP patch version, eg. 1.11 + fm_s32 reserve; +}; + +typedef struct fm_i2s_info { + fm_s32 status; + fm_s32 mode; + fm_s32 rate; +} fm_i2s_info_t; + + +struct fm_platform { + struct cdev cdev; + dev_t dev_t; + struct class *cls; + struct device *dev; +}; + +struct fm { + //chip info + fm_u16 chip_id; //chip id, such as 6616/6620/6626/6628 + fm_u16 device_id; //chip version + //basic run time info + fm_s32 ref; //fm driver can be multi opened + fm_bool chipon; //Chip power state + enum fm_pwr_state pwr_sta; //FM module power state + enum fm_op_state op_sta; //current operation state: tune, seek, scan ... + enum fm_audio_path aud_path; //I2S or Analog + fm_s32 vol; //current audio volume from chip side + fm_bool mute; // true: mute, false: playing + fm_bool rds_on; // true: on, false: off + enum fm_antenna_type ana_type; //long/short antenna + fm_bool via_bt; // true: fm over bt controller; false: fm over host + fm_u16 min_freq; // for UE, 875KHz + fm_u16 max_freq; // for UE, 1080KHz + fm_u16 cur_freq; //current frequency + fm_u8 band; // UE/JAPAN/JPANWD + /*FM Tx*/ + fm_u32 vcoon;//TX VCO tracking ON duiration(ms) + fm_u32 vcooff;//TX RTC VCO tracking interval(s) + fm_u32 txpwrctl;//TX power contrl interval(s) + fm_u32 tx_pwr; + fm_bool rdstx_on; //false:rds tx off, true:rds tx on + //RDS data + struct fm_flag_event *rds_event;//pointer to rds event + struct rds_t *pstRDSData; //rds spec data buffer + //platform data + struct fm_platform platform; //platform related members + + struct fm_workthread *eint_wkthd; + struct fm_workthread *timer_wkthd; + struct fm_work *eint_wk; + struct fm_work *rds_wk; + struct fm_work *rst_wk; //work for subsystem reset + //Tx + struct fm_work *fm_tx_desense_wifi_work; + struct fm_work *fm_tx_power_ctrl_work; + +}; + +struct fm_callback { + //call backs + fm_u16(*cur_freq_get)(void); + fm_s32(*cur_freq_set)(fm_u16 new_freq); +// fm_u16(*chan_para_get)(fm_u16 freq); //get channel parameter, HL side/ FA / ATJ +}; + +struct fm_basic_interface { + //mt66x6 lib interfaces + fm_s32(*low_pwr_wa)(fm_s32 onoff); + fm_s32(*pwron)(fm_s32 data); + fm_s32(*pwroff)(fm_s32 data); + fm_s32(*msdelay)(fm_u32 val); + fm_s32(*usdelay)(fm_u32 val); + fm_s32(*read)(fm_u8 addr, fm_u16 *val); + fm_s32(*write)(fm_u8 addr, fm_u16 val); + fm_s32(*setbits)(fm_u8 addr, fm_u16 bits, fm_u16 msk); + fm_u16(*chipid_get)(void); + fm_s32(*mute)(fm_bool mute); + fm_s32(*rampdown)(void); + fm_s32(*pwrupseq)(fm_u16 *chip_id, fm_u16 *device_id); + fm_s32(*pwrdownseq)(void); + fm_bool(*setfreq)(fm_u16 freq); + fm_bool(*seek)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 dir, fm_u16 space); + fm_s32(*seekstop)(void); + fm_bool(*scan)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 *tbl, fm_u16 *tblsize, fm_u16 dir, fm_u16 space); + fm_bool(*jammer_scan)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 *tbl, fm_u16 *tblsize, fm_u16 dir, fm_u16 space); + fm_s32(*cqi_get)(fm_s8 *buf, fm_s32 buf_len); + fm_s32(*scanstop)(void); + fm_s32(*rssiget)(fm_s32 *rssi); + fm_s32(*volset)(fm_u8 vol); + fm_s32(*volget)(fm_u8 *vol); + fm_s32(*dumpreg)(void); + fm_bool(*msget)(fm_u16 *ms); //mono/stereo indicator get + fm_s32(*msset)(fm_s32 ms); //mono/stereo force set + fm_bool(*pamdget)(fm_u16 *pamd); + fm_bool(*em)(fm_u16 group, fm_u16 item, fm_u32 val); + fm_s32(*anaswitch)(fm_s32 ana); + fm_s32(*anaget)(void); + fm_s32(*caparray_get)(fm_s32 *ca); + fm_s32(*i2s_set)(fm_s32 onoff, fm_s32 mode, fm_s32 sample); + fm_s32(*i2s_get)(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample); + fm_s32(*hwinfo_get)(struct fm_hw_info *req); + fm_s32(*is_dese_chan)(fm_u16 freq); // check if this is a de-sense channel + fm_s32(*softmute_tune)(fm_u16 freq,fm_s32 *rssi,fm_bool *valid); + fm_s32(*desense_check)(fm_u16 freq,fm_s32 rssi); // check if this is a valid channel + fm_s32(*get_freq_cqi)(fm_u16 freq,fm_s32 *cqi); + fm_s32(*cqi_log)(fm_s32 min_freq, fm_s32 max_freq,fm_s32 space, fm_s32 cnt);//cqi log tool + fm_s32(*fm_via_bt)(fm_bool flag);//fm over BT:1:enable,0:disable + /*tx function*/ + fm_s32(*tx_support)(fm_s32 *sup); + fm_s32(*rdstx_enable)(fm_s32 *flag); + fm_bool(*tune_tx)(fm_u16 freq); + fm_s32(*pwrupseq_tx)(void); + fm_s32(*pwrdownseq_tx)(void); + fm_s32 (*tx_pwr_ctrl)(fm_u16 freq, fm_s32 *ctr); + fm_s32 (*rtc_drift_ctrl)(fm_u16 freq, fm_s32 *ctr); + fm_s32 (*tx_desense_wifi)(fm_u16 freq, fm_s32 *ctr); + fm_s32 (*tx_scan)(fm_u16 min_freq, fm_u16 max_freq,fm_u16 *pFreq,fm_u16 *pScanTBL,fm_u16 *ScanTBLsize,fm_u16 scandir,fm_u16 space); +}; + +struct fm_rds_interface { + //rds lib interfaces + fm_s32(*rds_blercheck)(rds_t *dst); + fm_bool(*rds_onoff)(rds_t *dst, fm_bool onoff); + fm_s32(*rds_parser)(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)); + fm_u16(*rds_gbc_get)(void); //good block counter + fm_u16(*rds_bbc_get)(void); //bad block counter + fm_u8(*rds_bbr_get)(void); //bad block ratio + fm_s32(*rds_bc_reset)(void); //reset block counter + fm_u32(*rds_bci_get)(void); //bler check interval + fm_s32(*rds_log_get)(struct rds_rx_t *dst, fm_s32 *dst_len); + fm_s32(*rds_gc_get)(struct rds_group_cnt_t *dst, rds_t *rdsp); + fm_s32(*rds_gc_reset)(rds_t *rdsp); + /*Tx*/ + fm_s32(*rds_tx)(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt); + fm_s32(*rds_tx_enable)(void); + fm_s32(*rds_tx_disable)(void); + fm_s32(*rdstx_support)(fm_s32 *sup); +}; + +struct fm_lowlevel_ops { + struct fm_callback cb; + struct fm_basic_interface bi; + struct fm_rds_interface ri; +}; + +#if (!defined(MT6620_FM)&&!defined(MT6628_FM)) +extern fm_s32 fm_low_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 fm_low_ops_unregister(struct fm_lowlevel_ops *ops); +extern fm_s32 fm_rds_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 fm_rds_ops_unregister(struct fm_lowlevel_ops *ops); +#endif +#ifdef MT6620_FM +extern fm_s32 MT6620fm_low_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6620fm_low_ops_unregister(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6620fm_rds_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6620fm_rds_ops_unregister(struct fm_lowlevel_ops *ops); +#endif +#ifdef MT6628_FM +extern fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6628fm_rds_ops_register(struct fm_lowlevel_ops *ops); +extern fm_s32 MT6628fm_rds_ops_unregister(struct fm_lowlevel_ops *ops); +#endif +/* + * fm_get_channel_space - get the spcace of gived channel + * @freq - value in 760~1080 or 7600~10800 + * + * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0 + */ + +extern fm_s32 fm_get_channel_space(int freq); +#endif //__FM_INTERFACE_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h new file mode 100755 index 000000000000..9fb403e75b0f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h @@ -0,0 +1,80 @@ +#ifndef __FM_IOCTL_H__ +#define __FM_IOCTL_H__ +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_main.h" + +#define FM_IOC_MAGIC 0xf5 // FIXME: any conflict? + +#define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*) +#define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t*) +#define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*) +#define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*) +#define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t*) +#define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t*) +#define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t*) +#define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t*) +#define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*) +#define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9) +#define FM_IOCTL_POWERUP_TX _IOWR(FM_IOC_MAGIC, 20, struct fm_tune_parm*) +#define FM_IOCTL_TUNE_TX _IOWR(FM_IOC_MAGIC, 21, struct fm_tune_parm*) +#define FM_IOCTL_RDS_TX _IOWR(FM_IOC_MAGIC, 22, struct fm_rds_tx_parm*) + +//IOCTL and struct for test +#define FM_IOCTL_GETCHIPID _IOWR(FM_IOC_MAGIC, 10, uint16_t*) +#define FM_IOCTL_EM_TEST _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*) +#define FM_IOCTL_RW_REG _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*) +#define FM_IOCTL_GETMONOSTERO _IOWR(FM_IOC_MAGIC, 13, uint16_t*) +#define FM_IOCTL_GETCURPAMD _IOWR(FM_IOC_MAGIC, 14, uint16_t*) +#define FM_IOCTL_GETGOODBCNT _IOWR(FM_IOC_MAGIC, 15, uint16_t*) +#define FM_IOCTL_GETBADBNT _IOWR(FM_IOC_MAGIC, 16, uint16_t*) +#define FM_IOCTL_GETBLERRATIO _IOWR(FM_IOC_MAGIC, 17, uint16_t*) + +//IOCTL for RDS +#define FM_IOCTL_RDS_ONOFF _IOWR(FM_IOC_MAGIC, 18, uint16_t*) +#define FM_IOCTL_RDS_SUPPORT _IOWR(FM_IOC_MAGIC, 19, int32_t*) + +#define FM_IOCTL_RDS_SIM_DATA _IOWR(FM_IOC_MAGIC, 23, uint32_t*) +#define FM_IOCTL_IS_FM_POWERED_UP _IOWR(FM_IOC_MAGIC, 24, uint32_t*) + +//IOCTL for FM Tx +#define FM_IOCTL_TX_SUPPORT _IOWR(FM_IOC_MAGIC, 25, int32_t*) +#define FM_IOCTL_RDSTX_SUPPORT _IOWR(FM_IOC_MAGIC, 26, int32_t*) +#define FM_IOCTL_RDSTX_ENABLE _IOWR(FM_IOC_MAGIC, 27, int32_t*) +#define FM_IOCTL_TX_SCAN _IOWR(FM_IOC_MAGIC, 28, struct fm_tx_scan_parm*) + +//IOCTL for FM over BT +#define FM_IOCTL_OVER_BT_ENABLE _IOWR(FM_IOC_MAGIC, 29, int32_t*) + +//IOCTL for FM ANTENNA SWITCH +#define FM_IOCTL_ANA_SWITCH _IOWR(FM_IOC_MAGIC, 30, int32_t*) +#define FM_IOCTL_GETCAPARRAY _IOWR(FM_IOC_MAGIC, 31, int32_t*) + +//IOCTL for FM compensation by GPS RTC +#define FM_IOCTL_GPS_RTC_DRIFT _IOWR(FM_IOC_MAGIC, 32, struct fm_gps_rtc_info*) + +//IOCTL for FM I2S Setting +#define FM_IOCTL_I2S_SETTING _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*) + +#define FM_IOCTL_RDS_GROUPCNT _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req_t*) +#define FM_IOCTL_RDS_GET_LOG _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_t*) + +#define FM_IOCTL_SCAN_GETRSSI _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*) +#define FM_IOCTL_SETMONOSTERO _IOWR(FM_IOC_MAGIC, 37, int32_t) + +#define FM_IOCTL_RDS_BC_RST _IOWR(FM_IOC_MAGIC, 38, int32_t*) +#define FM_IOCTL_CQI_GET _IOWR(FM_IOC_MAGIC, 39, struct fm_cqi_req*) +#define FM_IOCTL_GET_HW_INFO _IOWR(FM_IOC_MAGIC, 40, struct fm_hw_info*) +#define FM_IOCTL_GET_I2S_INFO _IOWR(FM_IOC_MAGIC, 41, struct fm_i2s_info*) +#define FM_IOCTL_IS_DESE_CHAN _IOWR(FM_IOC_MAGIC, 42, int32_t*) + +#define FM_IOCTL_SCAN_NEW _IOWR(FM_IOC_MAGIC, 60, struct fm_scan_t*) +#define FM_IOCTL_SEEK_NEW _IOWR(FM_IOC_MAGIC, 61, struct fm_seek_t*) +#define FM_IOCTL_TUNE_NEW _IOWR(FM_IOC_MAGIC, 62, struct fm_tune_t*) +#define FM_IOCTL_SOFT_MUTE_TUNE _IOWR(FM_IOC_MAGIC, 63, struct fm_softmute_tune_t*)/*for soft mute tune*/ +#define FM_IOCTL_DESENSE_CHECK _IOWR(FM_IOC_MAGIC, 64, fm_desense_check_t*) + +#define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF) + +#endif //__FM_IOCTL_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h new file mode 100755 index 000000000000..696a1dd565e7 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h @@ -0,0 +1,218 @@ +#ifndef __FM_LINK_H__ +#define __FM_LINK_H__ + +#include "fm_typedef.h" +#include "fm_rds.h" + +typedef enum { + FM_TASK_RX_PARSER_PKT_TYPE = 0, + FM_TASK_RX_PARSER_OPCODE, + FM_TASK_RX_PARSER_PKT_LEN_1, + FM_TASK_RX_PARSER_PKT_LEN_2, + FM_TASK_RX_PARSER_PKT_PAYLOAD, + FM_TASK_RX_PARSER_BUFFER_CONGESTION +} fm_task_parser_state; + +enum { + FM_TASK_COMMAND_PKT_TYPE = 0x01, + FM_TASK_EVENT_PKT_TYPE = 0x04 +}; + +enum { + FM_STP_TEST_OPCODE = 0x00, + FSPI_ENABLE_OPCODE = 0x01, + FSPI_MUX_SEL_OPCODE = 0x02, + FSPI_READ_OPCODE = 0x03, + FSPI_WRITE_OPCODE = 0x04, + FI2C_READ_OPCODE = 0x05, + FI2C_WRITE_OPCODE = 0x06, + FM_ENABLE_OPCODE = 0x07, + FM_RESET_OPCODE = 0x08, + FM_TUNE_OPCODE = 0x09, + FM_SEEK_OPCODE = 0x0a, + FM_SCAN_OPCODE = 0x0b, + RDS_RX_ENABLE_OPCODE = 0x0c, + RDS_RX_DATA_OPCODE = 0x0d, + FM_RAMPDOWN_OPCODE = 0x0e, + FM_MCUCLK_SEL_OPCODE = 0x0f, + FM_MODEMCLK_SEL_OPCODE = 0x10, + RDS_TX_OPCODE = 0x11, + FM_PATCH_DOWNLOAD_OPCODE = 0x12, + FM_COEFF_DOWNLOAD_OPCODE = 0x13, + FM_HWCOEFF_DOWNLOAD_OPCODE = 0x14, + FM_ROM_DOWNLOAD_OPCODE = 0x15, + FM_SOFT_MUTE_TUNE_OPCODE = 0x17, +}; + +enum { + FLAG_TEST = (1 << FM_STP_TEST_OPCODE), + FLAG_FSPI_EN = (1 << FSPI_ENABLE_OPCODE), + FLAG_FSPI_MUXSEL = (1 << FSPI_MUX_SEL_OPCODE), + FLAG_FSPI_RD = (1 << FSPI_READ_OPCODE), + FLAG_FSPI_WR = (1 << FSPI_WRITE_OPCODE), + FLAG_I2C_RD = (1 << FI2C_READ_OPCODE), + FLAG_I2C_WR = (1 << FI2C_WRITE_OPCODE), + FLAG_EN = (1 << FM_ENABLE_OPCODE), + FLAG_RST = (1 << FM_RESET_OPCODE), + FLAG_TUNE = (1 << FM_TUNE_OPCODE), + FLAG_SEEK = (1 << FM_SEEK_OPCODE), + FLAG_SCAN = (1 << FM_SCAN_OPCODE), + FLAG_RDS_RX_EN = (1 << RDS_RX_ENABLE_OPCODE), + FLAG_RDS_DATA = (1 << RDS_RX_DATA_OPCODE), + FLAG_RAMPDOWN = (1 << FM_RAMPDOWN_OPCODE), + FLAG_MCUCLK = (1 << FM_MCUCLK_SEL_OPCODE), + FLAG_MODEMCLK = (1 << FM_MODEMCLK_SEL_OPCODE), + FLAG_RDS_TX = (1 << RDS_TX_OPCODE), + FLAG_PATCH = (1 << FM_PATCH_DOWNLOAD_OPCODE), + FLAG_COEFF = (1 << FM_COEFF_DOWNLOAD_OPCODE), + FLAG_HWCOEFF = (1 << FM_HWCOEFF_DOWNLOAD_OPCODE), + FLAG_ROM = (1 << FM_ROM_DOWNLOAD_OPCODE), + FLAG_SM_TUNE = (1 << FM_SOFT_MUTE_TUNE_OPCODE), // 23 + FLAG_CQI_DONE = (1 << 27), + FLAG_TUNE_DONE = (1 << 28), + FLAG_SEEK_DONE = (1 << 29), + FLAG_SCAN_DONE = (1 << 30), + FLAG_TERMINATE = (1 << 31) +}; + +#define FM_SCANTBL_SIZE 16 +#define FM_CQI_BUF_SIZE 96 +struct fm_res_ctx { + fm_u16 fspi_rd; + fm_u16 seek_result; + fm_u16 scan_result[FM_SCANTBL_SIZE]; + fm_s8 cqi[FM_CQI_BUF_SIZE]; + struct rds_rx_t rds_rx_result; +}; + +#define FM_TRACE_ENABLE + +#define FM_TRACE_FIFO_SIZE 200 +#define FM_TRACE_PKT_SIZE 60 +struct fm_trace_t { + fm_s32 type; + fm_s32 opcode; + fm_s32 len; + fm_u8 pkt[FM_TRACE_PKT_SIZE]; // full packet + unsigned long time; + fm_s32 tid; +}; + +struct fm_trace_fifo_t { + fm_s8 name[20+1]; + struct fm_trace_t trace[FM_TRACE_FIFO_SIZE]; + fm_u32 size; + fm_u32 in; + fm_u32 out; + fm_u32 len; + fm_s32 (*trace_in)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra); + fm_s32 (*trace_out)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra); + fm_bool (*is_full)(struct fm_trace_fifo_t *thiz); + fm_bool (*is_empty)(struct fm_trace_fifo_t *thiz); +}; + +#define FM_TRACE_IN(fifop, tracep) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->trace_in){ \ + __ret = (fifop)->trace_in(fifop, tracep); \ + } \ + __ret; \ +}) + +#define FM_TRACE_OUT(fifop, tracep) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->trace_out){ \ + __ret = (fifop)->trace_out(fifop, tracep); \ + } \ + __ret; \ +}) + +#define FM_TRACE_FULL(fifop) \ +({ \ + fm_bool __ret = (fm_bool)fm_false; \ + if(fifop && (fifop)->is_full){ \ + __ret = (fifop)->is_full(fifop); \ + } \ + __ret; \ +}) + +#define FM_TRACE_EMPTY(fifop) \ +({ \ + fm_bool __ret = (fm_bool)fm_false; \ + if(fifop && (fifop)->is_empty){ \ + __ret = (fifop)->is_empty(fifop); \ + } \ + __ret; \ +}) + +#if (defined(MT6620_FM)||defined(MT6628_FM)) +#include "fm_utils.h" + +#define RX_BUF_SIZE 128 +#define TX_BUF_SIZE 1024 + +#define SW_RETRY_CNT (1) +#define SW_RETRY_CNT_MAX (5) +#define SW_WAIT_TIMEOUT_MAX (100) +// FM operation timeout define for error handle +#define TEST_TIMEOUT (3) +#define FSPI_EN_TIMEOUT (3) +#define FSPI_MUXSEL_TIMEOUT (3) +#define FSPI_RD_TIMEOUT (3) +#define FSPI_WR_TIMEOUT (3) +#define I2C_RD_TIMEOUT (3) +#define I2C_WR_TIMEOUT (3) +#define EN_TIMEOUT (3) +#define RST_TIMEOUT (3) +#define TUNE_TIMEOUT (3) +#define SM_TUNE_TIMEOUT (6) +#define SEEK_TIMEOUT (15) +#define SCAN_TIMEOUT (15) //usualy scan will cost 10 seconds +#define RDS_RX_EN_TIMEOUT (3) +#define RDS_DATA_TIMEOUT (100) +#define RAMPDOWN_TIMEOUT (3) +#define MCUCLK_TIMEOUT (3) +#define MODEMCLK_TIMEOUT (3) +#define RDS_TX_TIMEOUT (3) +#define PATCH_TIMEOUT (3) +#define COEFF_TIMEOUT (3) +#define HWCOEFF_TIMEOUT (3) +#define ROM_TIMEOUT (3) + +struct fm_link_event { + struct fm_flag_event *ln_event; + struct fm_res_ctx result; // seek/scan/read/RDS +}; +#endif + +/* + * FM data and ctrl link APIs: platform related and bus related + */ +extern fm_s32 fm_link_setup(void* data); + +extern fm_s32 fm_link_release(void); + +extern fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result)); + +extern fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32)); + +extern fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val); + +extern fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val); + +extern fm_s32 fm_force_active_event(fm_u32 mask); + +extern fm_bool fm_wait_stc_done(fm_u32 sec); + +extern struct fm_trace_fifo_t* fm_trace_fifo_create(const fm_s8 *name); + +extern fm_s32 fm_trace_fifo_release(struct fm_trace_fifo_t *fifo); + +extern fm_s32 fm_print_cmd_fifo(void); + +extern fm_s32 fm_print_evt_fifo(void); + +#endif //__FM_LINK_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h new file mode 100755 index 000000000000..12f5a0863147 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h @@ -0,0 +1,384 @@ +#ifndef __FM_MAIN_H__ +#define __FM_MAIN_H__ +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_rds.h" +#include "fm_eint.h" +#include "fm_link.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_private.h" + +#define FM_NAME "fm" +#define FM_DEVICE_NAME "/dev/fm" + +#define FM_VOL_MAX 0x2B // 43 volume(0-15) +#define FM_TIMER_TIMEOUT_DEFAULT 1000 +#define FM_TIMER_TIMEOUT_MIN 1000 +#define FM_TIMER_TIMEOUT_MAX 1000000 +//FM Tx +#define FM_TX_PWR_LEVEL_MAX 120 //FM transmitter power level, rang: 85db~120db, default 120db + +#define FM_TX_PWR_CTRL_INVAL_DEFAULT 10 +#define FM_TX_PWR_CTRL_INVAL_MIN 5 +#define FM_TX_PWR_CTRL_INVAL_MAX 10000 + +#define FM_TX_VCO_OFF_DEFAULT 5 +#define FM_TX_VCO_OFF_MIN 1 +#define FM_TX_VCO_OFF_MAX 10000 + +#define FM_TX_VCO_ON_DEFAULT 100 +#define FM_TX_VCO_ON_MIN 10 +#define FM_TX_VCO_ON_MAX 10000 + +#define FM_GPS_RTC_AGE_TH 2 +#define FM_GPS_RTC_DRIFT_TH 0 +#define FM_GPS_RTC_TIME_DIFF_TH 10 +#define FM_GPS_RTC_RETRY_CNT 1 +#define FM_GPS_RTC_DRIFT_MAX 5000 +enum{ + FM_GPS_RTC_INFO_OLD = 0, + FM_GPS_RTC_INFO_NEW = 1, + FM_GPS_RTC_INFO_MAX +}; + +typedef enum +{ + FM_OVER_BT_DISABLE = 0, + FM_OVER_BT_ENABLE +}fm_over_bt_enable_state; + +#define FM_RDS_ENABLE 0x01 // 1: enable RDS, 0:disable RDS +#define FM_RDS_DATA_READY (1 << 0) + +// errno +#define FM_SUCCESS 0 +#define FM_FAILED 1 +#define FM_EPARM 2 +#define FM_BADSTATUS 3 +#define FM_TUNE_FAILED 4 +#define FM_SEEK_FAILED 5 +#define FM_BUSY 6 +#define FM_SCAN_FAILED 7 + +struct fm_tune_parm { + fm_u8 err; + fm_u8 band; + fm_u8 space; + fm_u8 hilo; + fm_u16 freq; // IN/OUT parameter +}; + +struct fm_seek_parm { + fm_u8 err; + fm_u8 band; + fm_u8 space; + fm_u8 hilo; + fm_u8 seekdir; + fm_u8 seekth; + fm_u16 freq; // IN/OUT parameter +}; + +#ifdef MTK_FM_50KHZ_SUPPORT +struct fm_scan_parm { + fm_u8 err; + fm_u8 band; + fm_u8 space; + fm_u8 hilo; + fm_u16 freq; // OUT parameter + fm_u16 ScanTBL[26]; //need no less than the chip + fm_u16 ScanTBLSize; //IN/OUT parameter +}; +#else +struct fm_scan_parm { + fm_u8 err; + fm_u8 band; + fm_u8 space; + fm_u8 hilo; + fm_u16 freq; // OUT parameter + fm_u16 ScanTBL[16]; //need no less than the chip + fm_u16 ScanTBLSize; //IN/OUT parameter +}; +#endif + +struct fm_cqi { + fm_s32 ch; + fm_s32 rssi; + fm_s32 reserve; +}; + +struct fm_cqi_req { + fm_u16 ch_num; + fm_s32 buf_size; + fm_s8 *cqi_buf; +}; + +struct fm_ch_rssi { + fm_u16 freq; + fm_s32 rssi; +}; + +enum fm_scan_cmd_t { + FM_SCAN_CMD_INIT = 0, + FM_SCAN_CMD_START, + FM_SCAN_CMD_GET_NUM, + FM_SCAN_CMD_GET_CH, + FM_SCAN_CMD_GET_RSSI, + FM_SCAN_CMD_GET_CH_RSSI, + FM_SCAN_CMD_MAX +}; + +struct fm_scan_t { + enum fm_scan_cmd_t cmd; + fm_s32 ret; // 0, success; else error code + fm_u16 lower; // lower band, Eg, 7600 -> 76.0Mhz + fm_u16 upper; // upper band, Eg, 10800 -> 108.0Mhz + fm_s32 space; // 5: 50KHz, 10: 100Khz, 20: 200Khz + fm_s32 num; // valid channel number + void *priv; + fm_s32 sr_size; // scan result buffer size in bytes + union { + fm_u16 *ch_buf; // channel buffer + fm_s32 *rssi_buf; // rssi buffer + struct fm_ch_rssi *ch_rssi_buf; //channel and RSSI buffer + } sr; +}; + +struct fm_seek_t { + fm_s32 ret; // 0, success; else error code + fm_u16 freq; + fm_u16 lower; // lower band, Eg, 7600 -> 76.0Mhz + fm_u16 upper; // upper band, Eg, 10800 -> 108.0Mhz + fm_s32 space; // 5: 50KHz, 10: 100Khz, 20: 200Khz + fm_s32 dir; // 0: up; 1: down + fm_s32 th; // seek threshold in dbm(Eg, -95dbm) + void *priv; +}; + +struct fm_tune_t { + fm_s32 ret; // 0, success; else error code + fm_u16 freq; + fm_u16 lower; // lower band, Eg, 7600 -> 76.0Mhz + fm_u16 upper; // upper band, Eg, 10800 -> 108.0Mhz + fm_s32 space; // 5: 50KHz, 10: 100Khz, 20: 200Khz + void *priv; +}; + + +#ifdef MTK_FM_50KHZ_SUPPORT +struct fm_rssi_req { + fm_u16 num; + fm_u16 read_cnt; + struct fm_ch_rssi cr[26*16]; +}; +#else +struct fm_rssi_req { + fm_u16 num; + fm_u16 read_cnt; + struct fm_ch_rssi cr[16*16]; +}; +#endif + +struct fm_rds_tx_parm { + fm_u8 err; + fm_u16 pi; + fm_u16 ps[12]; // 4 ps + fm_u16 other_rds[87]; // 0~29 other groups + fm_u8 other_rds_cnt; // # of other group +}; + +typedef struct fm_rds_tx_req { + unsigned char pty; // 0~31 integer + unsigned char rds_rbds; // 0:RDS, 1:RBDS + unsigned char dyn_pty; // 0:static, 1:dynamic + unsigned short pi_code; // 2-byte hex + unsigned char ps_buf[8]; // hex buf of PS + unsigned char ps_len; // length of PS, must be 0 / 8" + unsigned char af; // 0~204, 0:not used, 1~204:(87.5+0.1*af)MHz + unsigned char ah; // Artificial head, 0:no, 1:yes + unsigned char stereo; // 0:mono, 1:stereo + unsigned char compress; // Audio compress, 0:no, 1:yes + unsigned char tp; // traffic program, 0:no, 1:yes + unsigned char ta; // traffic announcement, 0:no, 1:yes + unsigned char speech; // 0:music, 1:speech +} fm_rds_tx_req; + +#define TX_SCAN_MAX 10 +#define TX_SCAN_MIN 1 + +struct fm_tx_scan_parm { + fm_u8 err; + fm_u8 band; //87.6~108MHz + fm_u8 space; + fm_u8 hilo; + fm_u16 freq; // start freq, if less than band min freq, then will use band min freq + fm_u8 scandir; + fm_u16 ScanTBL[TX_SCAN_MAX]; //need no less than the chip + fm_u16 ScanTBLSize; //IN: desired size, OUT: scan result size +}; + +struct fm_gps_rtc_info { + fm_s32 err; //error number, 0: success, other: err code + fm_s32 retryCnt; //GPS mnl can decide retry times + fm_s32 ageThd; //GPS 3D fix time diff threshold + fm_s32 driftThd; //GPS RTC drift threshold + struct timeval tvThd; //time value diff threshold + fm_s32 age; //GPS 3D fix time diff + fm_s32 drift; //GPS RTC drift + union { + unsigned long stamp; //time stamp in jiffies + struct timeval tv; //time stamp value in RTC + }; + fm_s32 flag; //rw flag +}; + +typedef enum { + FM_I2S_ON = 0, + FM_I2S_OFF +} fm_i2s_state; + +typedef enum { + FM_I2S_MASTER = 0, + FM_I2S_SLAVE +} fm_i2s_mode; + +typedef enum { + FM_I2S_32K = 0, + FM_I2S_44K, + FM_I2S_48K +} fm_i2s_sample; + +struct fm_i2s_setting { + fm_s32 onoff; + fm_s32 mode; + fm_s32 sample; +}; +typedef struct +{ + fm_s32 freq; + fm_s32 rssi; +}fm_desense_check_t; + +typedef enum { + FM_RX = 0, + FM_TX = 1 +} FM_PWR_T; + +struct fm_ctl_parm { + fm_u8 err; + fm_u8 addr; + fm_u16 val; + fm_u16 rw_flag;//0:write, 1:read +}; +struct fm_em_parm { + fm_u16 group_idx; + fm_u16 item_idx; + fm_u32 item_value; +}; + +enum { + FM_SUBSYS_RST_OFF, + FM_SUBSYS_RST_START, + FM_SUBSYS_RST_END, + FM_SUBSYS_RST_MAX +}; +enum{ + FM_TX_PWR_CTRL_DISABLE, + FM_TX_PWR_CTRL_ENABLE, + FM_TX_PWR_CTRL_MAX +}; + +enum{ + FM_TX_RTC_CTRL_DISABLE, + FM_TX_RTC_CTRL_ENABLE, + FM_TX_RTC_CTRL_MAX +}; + +enum{ + FM_TX_DESENSE_DISABLE, + FM_TX_DESENSE_ENABLE, + FM_TX_DESENSE_MAX +}; + +struct fm_softmute_tune_t +{ + fm_s32 rssi; // RSSI of current channel + fm_u16 freq; //current frequency + fm_bool valid; //current channel is valid(true) or not(false) +}; + +//init and deinit APIs +extern fm_s32 fm_env_setup(void); +extern fm_s32 fm_env_destroy(void); +extern struct fm* fm_dev_init(fm_u32 arg); +extern fm_s32 fm_dev_destroy(struct fm *fm); + + +//fm main basic APIs +extern enum fm_pwr_state fm_pwr_state_get(struct fm *fmp); +extern enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta); +extern fm_s32 fm_open(struct fm *fmp); +extern fm_s32 fm_close(struct fm *fmp); +extern fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len); +extern fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm); +extern fm_s32 fm_powerdown(struct fm *fm); +extern fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm); +extern fm_s32 fm_scan(struct fm *fm, struct fm_scan_parm *parm); +extern fm_s32 fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size); +extern fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req); +extern fm_s32 fm_hwscan_stop(struct fm *fm); +extern fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna); +extern fm_s32 fm_setvol(struct fm *fm, fm_u32 vol); +extern fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol); +extern fm_s32 fm_mute(struct fm *fm, fm_u32 bmute); +extern fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi); +extern fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val); +extern fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val); +extern fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid); +extern fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms); +extern fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms); +extern fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd); +extern fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca); +extern fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val); +extern fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off); +extern fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc); +extern fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc); +extern fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr); +extern fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst); +extern fm_s32 fm_rds_group_cnt_reset(struct fm *fm); +extern fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len); +extern fm_s32 fm_rds_block_cnt_reset(struct fm *fm); +extern fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample); +extern fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req); +extern fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm); +extern fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq); +extern fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi); +extern fm_s32 fm_sys_state_get(struct fm *fmp); +extern fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta); +extern fm_s32 fm_subsys_reset(struct fm *fm); + +extern fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm); +extern fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm); +extern fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm); + +extern fm_s32 fm_cust_config_setup(fm_s8 * filename); +extern fm_s32 fm_cqi_log(void); +extern fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm); +extern fm_s32 fm_dump_reg(void); +extern fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src); +extern fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag); + +/*tx function*/ +extern fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support); + +extern fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm); +extern fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm); +extern fm_s32 fm_powerdowntx(struct fm *fm); +extern fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm); +extern fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support); +extern fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support); +extern fm_s32 fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm); + +#endif //__FM_MAIN_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h new file mode 100755 index 000000000000..bd56300fb4a8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h @@ -0,0 +1,29 @@ +#ifndef __FM_PATCH_H__ +#define __FM_PATCH_H__ + +enum { + FM_ROM_V1 = 0, + FM_ROM_V2 = 1, + FM_ROM_V3 = 2, + FM_ROM_V4 = 3, + FM_ROM_V5 = 4, + FM_ROM_MAX +}; + +struct fm_patch_tbl { + fm_s32 idx; + fm_s8 *patch; + fm_s8 *coeff; + fm_s8 *rom; + fm_s8 *hwcoeff; +}; + +extern fm_s32 fm_file_exist(const fm_s8 *filename); + +extern fm_s32 fm_file_read(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 position); + +extern fm_s32 fm_file_write(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 *ppos); + + +#endif //__FM_PATCH_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h new file mode 100755 index 000000000000..9d0a92964a30 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h @@ -0,0 +1,219 @@ +#ifndef __FM_RDS_H__ +#define __FM_RDS_H__ +#include "fm_typedef.h" + +//FM_RDS_DATA_CRC_FFOST +#define FM_RDS_GDBK_IND_A (0x08) +#define FM_RDS_GDBK_IND_B (0x04) +#define FM_RDS_GDBK_IND_C (0x02) +#define FM_RDS_GDBK_IND_D (0x01) +#define FM_RDS_DCO_FIFO_OFST (0x01E0) +#define FM_RDS_READ_DELAY (0x80) + +#define RDS_RX_BLOCK_PER_GROUP (4) +#define RDS_RX_GROUP_SIZE (2*RDS_RX_BLOCK_PER_GROUP) +#define MAX_RDS_RX_GROUP_CNT (12) +#define RDS_RT_MULTI_REV_TH 100 + +typedef struct rds_packet_t { + fm_u16 blkA; + fm_u16 blkB; + fm_u16 blkC; + fm_u16 blkD; + fm_u16 cbc; //correct bit cnt + fm_u16 crc; //crc checksum +} rds_packet_t; + +typedef struct rds_rx_t { + fm_u16 sin; + fm_u16 cos; + rds_packet_t data[MAX_RDS_RX_GROUP_CNT]; +} rds_rx_t; + +typedef enum rds_ps_state_machine_t { + RDS_PS_START = 0, + RDS_PS_DECISION, + RDS_PS_GETLEN, + RDS_PS_DISPLAY, + RDS_PS_FINISH, + RDS_PS_MAX +} rds_ps_state_machine_t; + +typedef enum rds_rt_state_machine_t { + RDS_RT_START = 0, + RDS_RT_DECISION, + RDS_RT_GETLEN, + RDS_RT_DISPLAY, + RDS_RT_FINISH, + RDS_RT_MAX +} rds_rt_state_machine_t; + + +enum { + RDS_GRP_VER_A = 0, //group version A + RDS_GRP_VER_B +}; + +typedef enum rds_blk_t { + RDS_BLK_A = 0, + RDS_BLK_B, + RDS_BLK_C, + RDS_BLK_D, + RDS_BLK_MAX +} rds_blk_t; + +//For RDS feature, these strcutures also be defined in "fm.h" +typedef struct rds_flag_t { + fm_u8 TP; + fm_u8 TA; + fm_u8 Music; + fm_u8 Stereo; + fm_u8 Artificial_Head; + fm_u8 Compressed; + fm_u8 Dynamic_PTY; + fm_u8 Text_AB; + fm_u32 flag_status; +} rds_flag_t; + +typedef struct rds_ct_t { + fm_u16 Month; + fm_u16 Day; + fm_u16 Year; + fm_u16 Hour; + fm_u16 Minute; + fm_u8 Local_Time_offset_signbit; + fm_u8 Local_Time_offset_half_hour; +} rds_ct_t; + +typedef struct rds_af_t { + fm_s16 AF_Num; + fm_s16 AF[2][25]; //100KHz + fm_u8 Addr_Cnt; + fm_u8 isMethod_A; + fm_u8 isAFNum_Get; +} rds_af_t; + +typedef struct rds_ps_t { + fm_u8 PS[4][8]; + fm_u8 Addr_Cnt; +} rds_ps_t; + +typedef struct rds_rt_t { + fm_u8 TextData[4][64]; + fm_u8 GetLength; + fm_u8 isRTDisplay; + fm_u8 TextLength; + fm_u8 isTypeA; + fm_u8 BufCnt; + fm_u16 Addr_Cnt; +} rds_rt_t; + +typedef struct rds_raw_t { + fm_s32 dirty; //indicate if the data changed or not + fm_s32 len; //the data len form chip + fm_u8 data[146]; +} rds_raw_t; + +typedef struct rds_group_cnt_t { + unsigned long total; + unsigned long groupA[16]; //RDS groupA counter + unsigned long groupB[16]; //RDS groupB counter +} rds_group_cnt_t; + +typedef enum rds_group_cnt_op_t { + RDS_GROUP_CNT_READ = 0, + RDS_GROUP_CNT_WRITE, + RDS_GROUP_CNT_RESET, + RDS_GROUP_CNT_MAX +} rds_group_cnt_op_t; + +typedef struct rds_group_cnt_req_t { + fm_s32 err; + enum rds_group_cnt_op_t op; + struct rds_group_cnt_t gc; +} rds_group_cnt_req_t; + +typedef struct rds_t { + struct rds_ct_t CT; + struct rds_flag_t RDSFlag; + fm_u16 PI; + fm_u8 Switch_TP; + fm_u8 PTY; + struct rds_af_t AF_Data; + struct rds_af_t AFON_Data; + fm_u8 Radio_Page_Code; + fm_u16 Program_Item_Number_Code; + fm_u8 Extend_Country_Code; + fm_u16 Language_Code; + struct rds_ps_t PS_Data; + fm_u8 PS_ON[8]; + struct rds_rt_t RT_Data; + fm_u16 event_status; //will use RDSFlag_Struct RDSFlag->flag_status to check which event, is that ok? + struct rds_group_cnt_t gc; +} rds_t; + + +//Need care the following definition. +//valid Rds Flag for notify +typedef enum rds_flag_status_t { + RDS_FLAG_IS_TP = 0x0001, // Program is a traffic program + RDS_FLAG_IS_TA = 0x0002, // Program currently broadcasts a traffic ann. + RDS_FLAG_IS_MUSIC = 0x0004, // Program currently broadcasts music + RDS_FLAG_IS_STEREO = 0x0008, // Program is transmitted in stereo + RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording + RDS_FLAG_IS_COMPRESSED = 0x0020, // Program content is compressed + RDS_FLAG_IS_DYNAMIC_PTY = 0x0040, // Program type can change + RDS_FLAG_TEXT_AB = 0x0080 // If this flag changes state, a new radio text string begins +} rds_flag_status_t; + +typedef enum rds_event_status_t { + RDS_EVENT_FLAGS = 0x0001, // One of the RDS flags has changed state + RDS_EVENT_PI_CODE = 0x0002, // The program identification code has changed + RDS_EVENT_PTY_CODE = 0x0004, // The program type code has changed + RDS_EVENT_PROGRAMNAME = 0x0008, // The program name has changed + RDS_EVENT_UTCDATETIME = 0x0010, // A new UTC date/time is available + RDS_EVENT_LOCDATETIME = 0x0020, // A new local date/time is available + RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed + RDS_EVENT_AF = 0x0080, // Current Channel RF signal strength too weak, need do AF switch + RDS_EVENT_AF_LIST = 0x0100, // An alternative frequency list is ready + RDS_EVENT_AFON_LIST = 0x0200, // An alternative frequency list is ready + RDS_EVENT_TAON = 0x0400, // Other Network traffic announcement start + RDS_EVENT_TAON_OFF = 0x0800, // Other Network traffic announcement finished. + RDS_EVENT_RDS = 0x2000, // RDS Interrupt had arrived durint timer period + RDS_EVENT_NO_RDS = 0x4000, // RDS Interrupt not arrived durint timer period + RDS_EVENT_RDS_TIMER = 0x8000 // Timer for RDS Bler Check. ---- BLER block error rate +} rds_event_status_t; + + +#define RDS_LOG_SIZE 2 +struct rds_log_t { + struct rds_rx_t rds_log[RDS_LOG_SIZE]; + fm_s32 log_len[RDS_LOG_SIZE]; + fm_u32 size; + fm_u32 in; + fm_u32 out; + fm_u32 len; + fm_s32(*log_in)(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len); + fm_s32(*log_out)(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len); +}; + +extern fm_s32 rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)); +extern fm_s32 rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src); +extern fm_s32 rds_grp_counter_reset(struct rds_group_cnt_t *gc); +extern fm_s32 rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len); +extern fm_s32 rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len); + + +#define DEFINE_RDSLOG(name) \ + struct rds_log_t name = { \ + .size = RDS_LOG_SIZE, \ + .in = 0, \ + .out = 0, \ + .len = 0, \ + .log_in = rds_log_in, \ + .log_out = rds_log_out, \ + } + + +#endif //__FM_RDS_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h new file mode 100755 index 000000000000..560ebb01bea6 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h @@ -0,0 +1,61 @@ +#ifndef __FM_STDLIB_H__ +#define __FM_STDLIB_H__ + +#include "fm_typedef.h" +#include + +#if 1 +#define fm_memset(buf, a, len) \ +({ \ + void *__ret = (void*)0; \ + __ret = memset((buf), (a), (len)); \ + __ret; \ +}) + +#define fm_memcpy(dst, src, len) \ +({ \ + void *__ret = (void*)0; \ + __ret = memcpy((dst), (src), (len)); \ + __ret; \ +}) + +#define fm_malloc(len) \ +({ \ + void *__ret = (void*)0; \ + __ret = kmalloc(len, GFP_KERNEL); \ + __ret; \ +}) + +#define fm_zalloc(len) \ +({ \ + void *__ret = (void*)0; \ + __ret = kzalloc(len, GFP_KERNEL); \ + __ret; \ +}) + +#define fm_free(ptr) kfree(ptr) + +#define fm_vmalloc(len) \ +({ \ + void *__ret = (void*)0; \ + __ret = vmalloc(len); \ + __ret; \ +}) + +#define fm_vfree(ptr) vfree(ptr) + +#else +inline void* fm_memset(void *buf, fm_s8 val, fm_s32 len) +{ + return memset(buf, val, len); +} + +inline void* fm_memcpy(void *dst, const void *src, fm_s32 len) +{ + return memcpy(dst, src, len); +} + +#endif + +#endif //__FM_STDLIB_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h new file mode 100755 index 000000000000..d601bcf5b4d6 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h @@ -0,0 +1,36 @@ +#ifndef __FM_TYPEDEF_H__ +#define __FM_TYPEDEF_H__ + +typedef signed char fm_s8; +typedef signed short fm_s16; +typedef signed int fm_s32; +typedef signed long long fm_s64; +typedef unsigned char fm_u8; +typedef unsigned short fm_u16; +typedef unsigned int fm_u32; +typedef unsigned long long fm_u64; + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef NULL +#define NULL (0) +#endif + +#ifndef BOOL +typedef unsigned char BOOL; +#endif + +typedef enum fm_bool { + fm_false = 0, + fm_true = 1 +} fm_bool; + + +#endif //__FM_TYPEDEF_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h new file mode 100755 index 000000000000..9c5e9f026f1a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h @@ -0,0 +1,309 @@ +#ifndef __FM_UTILS_H__ +#define __FM_UTILS_H__ + +#include "fm_typedef.h" + + +/** + * Base structure of fm object + */ +#define FM_NAME_MAX 20 +struct fm_object { + fm_s8 name[FM_NAME_MAX+1]; // name of fm object + fm_u8 type; // type of fm object + fm_u8 flag; // flag of fm object + fm_s32 ref; + void *priv; + //struct fm_list *list; // list node of fm object +}; + + +/* + * FM FIFO + */ +struct fm_fifo { + struct fm_object obj; + fm_s32 size; + fm_s32 in; + fm_s32 out; + fm_s32 len; + fm_s32 item_size; + fm_s32 (*input)(struct fm_fifo *thiz, void *item); + fm_s32 (*output)(struct fm_fifo *thiz, void *item); + fm_bool (*is_full)(struct fm_fifo *thiz); + fm_bool (*is_empty)(struct fm_fifo *thiz); + fm_s32 (*get_total_len)(struct fm_fifo *thiz); + fm_s32 (*get_valid_len)(struct fm_fifo *thiz); + fm_s32 (*reset)(struct fm_fifo *thiz); +}; + +extern struct fm_fifo* fm_fifo_init(struct fm_fifo* fifo, void *buf, const fm_s8 *name, fm_s32 item_size, fm_s32 item_num); + +extern struct fm_fifo* fm_fifo_create(const fm_s8 *name, fm_s32 item_size, fm_s32 item_num); + +extern fm_s32 fm_fifo_release(struct fm_fifo *fifo); + +#define FM_FIFO_INPUT(fifop, item) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->input){ \ + __ret = (fifop)->input(fifop, item); \ + } \ + __ret; \ +}) + +#define FM_FIFO_OUTPUT(fifop, item) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->output){ \ + __ret = (fifop)->output(fifop, item); \ + } \ + __ret; \ +}) + +#define FM_FIFO_IS_FULL(fifop) \ +({ \ + fm_bool __ret = fm_false; \ + if(fifop && (fifop)->is_full){ \ + __ret = (fifop)->is_full(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_IS_EMPTY(fifop) \ +({ \ + fm_bool __ret = fm_false; \ + if(fifop && (fifop)->is_empty){ \ + __ret = (fifop)->is_empty(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_RESET(fifop) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->reset){ \ + __ret = (fifop)->reset(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_GET_TOTAL_LEN(fifop) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->get_total_len){ \ + __ret = (fifop)->get_total_len(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_GET_VALID_LEN(fifop) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(fifop && (fifop)->get_valid_len){ \ + __ret = (fifop)->get_valid_len(fifop); \ + } \ + __ret; \ +}) + + +/* + * FM asynchronous information mechanism + */ +struct fm_flag_event { + fm_s32 ref; + fm_s8 name[FM_NAME_MAX+1]; + void *priv; + + volatile fm_u32 flag; + + //flag methods + fm_u32(*send)(struct fm_flag_event* thiz, fm_u32 mask); + fm_s32(*wait)(struct fm_flag_event* thiz, fm_u32 mask); + long(*wait_timeout)(struct fm_flag_event* thiz, fm_u32 mask, long timeout); + fm_u32(*clr)(struct fm_flag_event* thiz, fm_u32 mask); + fm_u32(*get)(struct fm_flag_event* thiz); + fm_u32(*rst)(struct fm_flag_event* thiz); +}; + +extern struct fm_flag_event* fm_flag_event_create(const fm_s8 *name); + +extern fm_s32 fm_flag_event_get(struct fm_flag_event *thiz); + +extern fm_s32 fm_flag_event_put(struct fm_flag_event *thiz); + +#define FM_EVENT_SEND(eventp, mask) \ +({ \ + fm_u32 __ret = (fm_u32)0; \ + if(eventp && (eventp)->send){ \ + __ret = (eventp)->send(eventp, mask); \ + } \ + __ret; \ +}) + +#define FM_EVENT_WAIT(eventp, mask) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(eventp && (eventp)->wait){ \ + __ret = (eventp)->wait(eventp, mask); \ + } \ + __ret; \ +}) + +#define FM_EVENT_WAIT_TIMEOUT(eventp, mask, timeout) \ +({ \ + long __ret = (long)0; \ + if(eventp && (eventp)->wait_timeout){ \ + __ret = (eventp)->wait_timeout(eventp, mask, timeout); \ + } \ + __ret; \ +}) + +#define FM_EVENT_GET(eventp) \ +({ \ + fm_u32 __ret = (fm_u32)0; \ + if(eventp && (eventp)->get){ \ + __ret = (eventp)->get(eventp); \ + } \ + __ret; \ +}) + +#define FM_EVENT_RESET(eventp) \ +({ \ + fm_u32 __ret = (fm_u32)0; \ + if(eventp && (eventp)->rst){ \ + __ret = (eventp)->rst(eventp); \ + } \ + __ret; \ +}) + +#define FM_EVENT_CLR(eventp, mask) \ +({ \ + fm_u32 __ret = (fm_u32)0; \ + if(eventp && (eventp)->clr){ \ + __ret = (eventp)->clr(eventp, mask); \ + } \ + __ret; \ +}) + +/* + * FM lock mechanism + */ +struct fm_lock { + fm_s8 name[FM_NAME_MAX+1]; + fm_s32 ref; + void *priv; + + //lock methods + fm_s32(*lock)(struct fm_lock* thiz); + fm_s32(*trylock)(struct fm_lock *thiz,fm_s32 retryCnt); + fm_s32(*unlock)(struct fm_lock* thiz); +}; + +extern struct fm_lock* fm_lock_create(const fm_s8 *name); + +extern fm_s32 fm_lock_get(struct fm_lock *thiz); + +extern fm_s32 fm_lock_put(struct fm_lock *thiz); + +extern struct fm_lock* fm_spin_lock_create(const fm_s8 *name); + +extern fm_s32 fm_spin_lock_get(struct fm_lock *thiz); + +extern fm_s32 fm_spin_lock_put(struct fm_lock *thiz); + +#define FM_LOCK(a) \ +({ \ + fm_s32 __ret = (fm_s32)0; \ + if(a && (a)->lock){ \ + __ret = (a)->lock(a); \ + } \ + __ret; \ +}) + +#define FM_UNLOCK(a) \ +{ \ + if((a)->unlock){ \ + (a)->unlock(a); \ + } \ +} + + +/* + * FM timer mechanism + */ +enum fm_timer_ctrl { + FM_TIMER_CTRL_GET_TIME = 0, + FM_TIMER_CTRL_SET_TIME = 1, + FM_TIMER_CTRL_MAX +}; + +#define FM_TIMER_FLAG_ACTIVATED (1<<0) + +struct fm_timer { + fm_s32 ref; + fm_s8 name[FM_NAME_MAX+1]; + void *priv; // platform detail impliment + + fm_s32 flag; // timer active/inactive + void (*timeout_func)(unsigned long data); // timeout function + unsigned long data; // timeout function's parameter + signed long timeout_ms; // timeout tick + //Tx parameters + volatile fm_u32 count; + volatile fm_u8 tx_pwr_ctrl_en; + volatile fm_u8 tx_rtc_ctrl_en; + volatile fm_u8 tx_desense_en; + + //timer methods + fm_s32(*init)(struct fm_timer *thiz, void (*timeout)(unsigned long data), unsigned long data, signed long time, fm_s32 flag); + fm_s32(*start)(struct fm_timer *thiz); + fm_s32(*update)(struct fm_timer *thiz); + fm_s32(*stop)(struct fm_timer *thiz); + fm_s32(*control)(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void* arg); +}; + +extern struct fm_timer* fm_timer_create(const fm_s8 *name); + +extern fm_s32 fm_timer_get(struct fm_timer *thiz); + +extern fm_s32 fm_timer_put(struct fm_timer *thiz); + +/* + * FM work thread mechanism + */ +struct fm_work { + fm_s32 ref; + fm_s8 name[FM_NAME_MAX+1]; + void *priv; + + void (*work_func)(unsigned long data); + unsigned long data; + //work methods + fm_s32(*init)(struct fm_work *thiz, void (*work_func)(unsigned long data), unsigned long data); +}; + +extern struct fm_work* fm_work_create(const fm_s8 *name); + +extern fm_s32 fm_work_get(struct fm_work *thiz); + +extern fm_s32 fm_work_put(struct fm_work *thiz); + + +struct fm_workthread { + fm_s32 ref; + fm_s8 name[FM_NAME_MAX+1]; + void *priv; + + //workthread methods + fm_s32(*add_work)(struct fm_workthread *thiz, struct fm_work *work); +}; + +extern struct fm_workthread* fm_workthread_create(const fm_s8* name); + +extern fm_s32 fm_workthread_get(struct fm_workthread *thiz); + +extern fm_s32 fm_workthread_put(struct fm_workthread *thiz); + +#endif //__FM_UTILS_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h new file mode 100755 index 000000000000..8b137891791f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h @@ -0,0 +1 @@ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h new file mode 100755 index 000000000000..1a2e54463da1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h @@ -0,0 +1,54 @@ +/* mt6620_fm.h + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * MT6620 FM Radio Driver -- head file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MT6620_FM_H__ +#define __MT6620_FM_H__ + +#include "fm_typedef.h" + +//#define FM_PowerOn_with_ShortAntenna +#define MT6620_RSSI_TH_LONG 0xFF01 //FM radio long antenna RSSI threshold(11.375dBuV) +#define MT6620_RSSI_TH_SHORT 0xFEE0 //FM radio short antenna RSSI threshold(-1dBuV) +#define MT6620_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +#define MT6620_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define MT6620_SCAN_CH_SIZE 40 //FM radio scan max channel size +#define MT6620_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +#define MT6620_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) +#define MT6620_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) +#define MT6620_DEEMPHASIS_50us TRUE + +#define MT6620_SLAVE_ADDR 0xE0 //0x70 7-bit address +#define MT6620_MAX_COUNT 100 +#define MT6620_SCANTBL_SIZE 16 //16*uinit16_t + +#define AFC_ON 0x01 +#if AFC_ON +#define FM_MAIN_CTRL_INIT 0x480 +#else +#define FM_MAIN_CTRL_INIT 0x080 +#endif + +#define ext_clk //if define ext_clk use external reference clock or mask will use internal +#define MT6620_DEV "MT6620" + +#endif //end of #ifndef __MT6620_FM_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h new file mode 100755 index 000000000000..4a00dc9310e3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h @@ -0,0 +1,60 @@ +#ifndef __MT6620_FM_CMD_H__ +#define __MT6620_FM_CMD_H__ + +#include +#include "fm_typedef.h" + +/* FM basic-operation's opcode */ +#define FM_BOP_BASE (0x80) +enum { + FM_WRITE_BASIC_OP = (FM_BOP_BASE + 0x00), + FM_UDELAY_BASIC_OP = (FM_BOP_BASE + 0x01), + FM_RD_UNTIL_BASIC_OP = (FM_BOP_BASE + 0x02), + FM_MODIFY_BASIC_OP = (FM_BOP_BASE + 0x03), + FM_MSLEEP_BASIC_OP = (FM_BOP_BASE + 0x04), + FM_MAX_BASIC_OP = (FM_BOP_BASE + 0x05) +}; + +/* FM BOP's size */ +#define FM_WRITE_BASIC_OP_SIZE (3) +#define FM_UDELAY_BASIC_OP_SIZE (4) +#define FM_RD_UNTIL_BASIC_OP_SIZE (5) +#define FM_MODIFY_BASIC_OP_SIZE (5) +#define FM_MSLEEP_BASIC_OP_SIZE (4) + +fm_s32 mt6620_off_2_longANA_1(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6620_off_2_longANA_2(fm_u8 *buf, fm_s32 buf_size); + +fm_s32 mt6620_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6620_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6620_pwrup_digital_init_3(fm_u8 *buf, fm_s32 buf_size); + +fm_s32 mt6620_pwrdown(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6620_rampdown(fm_u8 *buf, fm_s32 buf_size); + +fm_s32 mt6620_tune_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq); +fm_s32 mt6620_tune_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq); +fm_s32 mt6620_tune_3(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq); +fm_s32 mt6620_fast_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq); +fm_s32 mt6620_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_s32 cnt, fm_s32 type); + +fm_s32 mt6620_seek_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6620_seek_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); + +fm_s32 mt6620_scan_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6620_scan_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); + +fm_s32 mt6620_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr); +fm_s32 mt6620_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value); +fm_s32 mt6620_rampdown_tx(unsigned char *tx_buf, int tx_buf_size); +fm_s32 mt6620_tune_txscan(unsigned char *tx_buf, int tx_buf_size, uint16_t freq); +fm_s32 mt6620_tune_tx(unsigned char *tx_buf, int tx_buf_size, uint16_t freq); +fm_s32 mt6620_rds_rx_enable(unsigned char *tx_buf, int tx_buf_size); +fm_s32 mt6620_rds_rx_disable(unsigned char *tx_buf, int tx_buf_size); +fm_s32 mt6620_rds_tx(unsigned char *tx_buf, int tx_buf_size, uint16_t pi, uint16_t *ps, uint16_t *other_rds, uint8_t other_rds_cnt); +fm_s32 mt6620_off_2_tx_shortANA(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6620_dig_init(fm_u8 *tx_buf, fm_s32 tx_buf_size); + +extern fm_s32 fm_get_channel_space(int freq); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h new file mode 100755 index 000000000000..b2c0910886c8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h @@ -0,0 +1,135 @@ +#ifndef __MT6620_FM_LIB_H__ +#define __MT6620_FM_LIB_H__ + +#include "fm_typedef.h" + +#define MT6620_VOL_MAX 0x2B // 43 volume(0-15) +enum { + DSPPATCH = 0xFFF9, + USDELAY = 0xFFFA, + MSDELAY = 0xFFFB, + HW_VER = 0xFFFD, + POLL_N = 0xFFFE, //poling check if bit(n) is '0' + POLL_P = 0xFFFF, //polling check if bit(n) is '1' +}; + +enum { + FM_PUS_DSPPATCH = DSPPATCH, + FM_PUS_USDELAY = USDELAY, + FM_PUS_MSDELAY = MSDELAY, + FM_PUS_HW_VER = HW_VER, + FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0' + FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1' + FM_PUS_MAX +}; + +enum { + DSP_PATH = 0x02, + DSP_COEFF = 0x03, + DSP_HW_COEFF = 0x04 +}; + +enum IMG_TYPE { + IMG_WRONG = 0, + IMG_ROM, + IMG_PATCH, + IMG_COEFFICIENT, + IMG_HW_COEFFICIENT +}; + +enum { + mt6620_E1 = 0, + mt6620_E2 +}; + +/*enum { + FM_LONG_ANA = 0, + FM_SHORT_ANA +};*/ +enum { + MT6620_I2S_ON = 0, + MT6620_I2S_OFF +}; + +enum { + MT6620_I2S_MASTER = 0, + MT6620_I2S_SLAVE +}; + +enum { + MT6620_I2S_32K = 0, + MT6620_I2S_44K, + MT6620_I2S_48K +}; + +struct mt6620_fm_i2s_info { + fm_s32 status; + fm_s32 mode; + fm_s32 rate; +}; +struct mt6620_fm_softmute_tune_cqi_t +{ + fm_u16 ch; //current frequency + fm_u16 rssi; // RSSI of current channel (raw data) + fm_u16 pamd; // PAMD of current channel (raw data) + fm_u16 mr; // MR of current channel (raw data) + fm_u16 atdc; // ATDC of current channel (raw data) + fm_u16 prx; // PRX of current channel (raw data) + fm_u16 smg; // soft mute gain of current channel (raw data) +}; + +#define BITn(n) (uint16_t)(1<<(n)) +#define MASK(n) (uint16_t)(~(1<<(n))) +//#define HiSideTableSize 1 +#define FM_TX_PWR_CTRL_FREQ_THR 890 +#define FM_TX_PWR_CTRL_TMP_THR_UP 45 +#define FM_TX_PWR_CTRL_TMP_THR_DOWN 0 + +#define FM_TX_TRACKING_TIME_MAX 10000 //TX VCO tracking time, default 100ms + +//#define MT6620_FPGA +//#define FM_MAIN_PGSEL (0x9F) +/* +#define FM_MAIN_BASE (0x0) +#define FM_MAIN_BITMAP0 (FM_MAIN_BASE + 0x80) +#define FM_MAIN_BITMAP1 (FM_MAIN_BASE + 0x81) +#define FM_MAIN_BITMAP2 (FM_MAIN_BASE + 0x82) +#define FM_MAIN_BITMAP3 (FM_MAIN_BASE + 0x83) +#define FM_MAIN_BITMAP4 (FM_MAIN_BASE + 0x84) +#define FM_MAIN_BITMAP5 (FM_MAIN_BASE + 0x85) +#define FM_MAIN_BITMAP6 (FM_MAIN_BASE + 0x86) +#define FM_MAIN_BITMAP7 (FM_MAIN_BASE + 0x87) +#define FM_MAIN_BITMAP8 (FM_MAIN_BASE + 0x88) +#define FM_MAIN_BITMAP9 (FM_MAIN_BASE + 0x89) +#define FM_MAIN_BITMAPA (FM_MAIN_BASE + 0x8a) +#define FM_MAIN_BITMAPB (FM_MAIN_BASE + 0x8b) +#define FM_MAIN_BITMAPC (FM_MAIN_BASE + 0x8c) +#define FM_MAIN_BITMAPD (FM_MAIN_BASE + 0x8d) +#define FM_MAIN_BITMAPE (FM_MAIN_BASE + 0x8e) +#define FM_MAIN_BITMAPF (FM_MAIN_BASE + 0x8f) +*/ +enum group_idx { + mono = 0, + stereo, + RSSI_threshold, + HCC_Enable, + PAMD_threshold, + Softmute_Enable, + De_emphasis, + HL_Side, + Demod_BW, + Dynamic_Limiter, + Softmute_Rate, + AFC_Enable, + Softmute_Level, + Analog_Volume, + GROUP_TOTAL_NUMS +}; + +enum item_idx { + Sblend_OFF = 0, + Sblend_ON, + ITEM_TOTAL_NUMS +}; + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h new file mode 100755 index 000000000000..42a5ebb5e964 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h @@ -0,0 +1,74 @@ +/* mt6620_fm_link.h + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * MT6620 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MT6620_FM_LINK_H__ +#define __MT6620_FM_LINK_H__ +#if 0 +#include +#include "fm_link.h" + +#define RX_BUF_SIZE 128 +#define TX_BUF_SIZE 1024 + +#define SW_RETRY_CNT (2) +#define SW_RETRY_CNT_MAX (5) +#define SW_WAIT_TIMEOUT_MAX (100) + +// FM operation timeout define for error handle +#define TEST_TIMEOUT (3) +#define FSPI_EN_TIMEOUT (3) +#define FSPI_MUXSEL_TIMEOUT (3) +#define FSPI_RD_TIMEOUT (3) +#define FSPI_WR_TIMEOUT (3) +#define I2C_RD_TIMEOUT (3) +#define I2C_WR_TIMEOUT (3) +#define EN_TIMEOUT (10) +#define RST_TIMEOUT (3) +#define TUNE_TIMEOUT (3) +#define SEEK_TIMEOUT (15) +#define SCAN_TIMEOUT (15) //usualy scan will cost 10 seconds +#define RDS_RX_EN_TIMEOUT (3) +#define RDS_DATA_TIMEOUT (100) +#define RAMPDOWN_TIMEOUT (3) +#define MCUCLK_TIMEOUT (3) +#define MODEMCLK_TIMEOUT (3) +#define RDS_TX_TIMEOUT (3) +#define PATCH_TIMEOUT (5) +#define COEFF_TIMEOUT (5) +#define HWCOEFF_TIMEOUT (5) +#define ROM_TIMEOUT (5) + +struct fm_link_event { + //data + volatile fm_u32 flag; + wait_queue_head_t wq; + struct fm_res_ctx result; // seek/scan/read/RDS + //methods + fm_u32(*set)(struct fm_link_event* thiz, fm_u32 mask); + fm_u32(*clr)(struct fm_link_event* thiz, fm_u32 mask); + long(*check)(struct fm_link_event* thiz, fm_u32 mask, long timeout); + fm_u32(*get)(struct fm_link_event* thiz); + fm_u32(*rst)(struct fm_link_event* thiz); +}; +#endif +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h new file mode 100755 index 000000000000..ce1f7882ce02 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h @@ -0,0 +1,98 @@ +#ifndef __MT6620_FM_REG_H__ +#define __MT6620_FM_REG_H__ + +enum MT6620_REG{ + FM_MAIN_CG1_CTRL = 0x60, + FM_MAIN_CG2_CTRL = 0x61, + FM_MAIN_HWVER = 0x62, + FM_MAIN_CTRL = 0x63, + FM_CHANNEL_SET = 0x65, + FM_MAIN_CFG1 = 0x66, + FM_MAIN_CFG2 = 0x67, + FM_MAIN_MCLKDESENSE = 0x38, + FM_MAIN_INTR = 0x69, + FM_MAIN_INTRMASK = 0x6A, + FM_MAIN_EXTINTRMASK = 0x6B, + FM_RSSI_IND = 0xE8, + FM_RSSI_TH = 0x6D, + FM_MAIN_RESET = 0x6E, + FM_MAIN_CHANDETSTAT = 0x6F, + FM_RDS_CFG0 = 0x80, + FM_RDS_INFO = 0x81, + FM_RDS_DATA_REG = 0x82, + FM_RDS_GOODBK_CNT = 0xC6, //page3 0xC6 + FM_RDS_BADBK_CNT = 0xC7, //page3 0xC7 + FM_RDS_PWDI = 0x85, + FM_RDS_PWDQ = 0x86, + FM_RDS_FIFO_STATUS0 = 0x87, + FM_FT_CON9 = 0x8F, + FM_DSP_PATCH_CTRL = 0x90, + FM_DSP_PATCH_OFFSET = 0x91, + FM_DSP_PATCH_DATA = 0x92, + FM_DSP_MEM_CTRL4 = 0x93, + FM_MAIN_PGSEL = 0x9F, + FM_ADDR_PAMD = 0xE9, + FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6, + FM_RDS_POINTER = 0xF0, + FM_MR_IND = 0xF2, +}; +#define FM_TXSCAN_RSSI_TH (-250) +#define FM_TXSCAN_PAMD_TH (-20) +#define FM_TXSCAN_MR_TH (-38) + +//RDS_BDGRP_ABD_CTRL_REG +enum{ + BDGRP_ABD_EN = 0x0001, + BER_RUN = 0x2000 +}; +#define FM_DAC_CON1 0x83 +#define FM_DAC_CON2 0x84 +#define FM_FT_CON0 0x86 +#define FM_I2S_CON0 0x90 +#define FM_STEROMONO_CTR (0xE0) +enum{ + FT_EN = 0x0001 +}; + +enum{ + I2S_EN = 0x0001, + FORMAT = 0x0002, + WLEN = 0x0004, + I2S_SRC = 0x0008 +}; + +//FM_MAIN_CTRL +enum{ + TUNE = 0x0001, + SEEK = 0x0002, + SCAN = 0x0004, + RDS_MASK = 0x0010, + MUTE = 0x0020, + RDS_BRST = 0x0040, + RAMP_DOWN = 0x0100, +}; + +//FM_MAIN_INTR +enum{ + FM_INTR_STC_DONE = 0x0001, + FM_INTR_IQCAL_DONE = 0x0002, + FM_INTR_DESENSE_HIT = 0x0004, + FM_INTR_CHNL_CHG = 0x0008, + FM_INTR_SW_INTR = 0x0010, + FM_INTR_RDS = 0x0020 +}; + +enum{ + ANTENNA_TYPE = 0x0010, +}; +//FM reg page +enum FM_PAGE{ + FM_PG0 = 0, + FM_PG1, + FM_PG2, + FM_PG3, + FM_PGMAX +}; + +#endif //__MT6620_FM_REG_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c new file mode 100755 index 000000000000..00ecfabf4a9f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c @@ -0,0 +1,1482 @@ +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_rds.h" +#include "fm_link.h" + +#include "mt6620_fm_reg.h" +//#include "mt6620_fm_link.h" +#include "mt6620_fm.h" +#include "mt6620_fm_cmd.h" +#include "mt6620_fm_cust_cfg.h" + +static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_WRITE_BASIC_OP; + buf[1] = FM_WRITE_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((value) & 0x00FF); + buf[4] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + + return (FM_WRITE_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_UDELAY_BASIC_OP; + buf[1] = FM_UDELAY_BASIC_OP_SIZE; + buf[2] = (fm_u8)((value) & 0x000000FF); + buf[3] = (fm_u8)((value >> 8) & 0x000000FF); + buf[4] = (fm_u8)((value >> 16) & 0x000000FF); + buf[5] = (fm_u8)((value >> 24) & 0x000000FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return (FM_UDELAY_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_RD_UNTIL_BASIC_OP; + buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask) & 0x00FF); + buf[4] = (fm_u8)((mask >> 8) & 0x00FF); + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_RD_UNTIL_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_MODIFY_BASIC_OP; + buf[1] = FM_MODIFY_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask_and) & 0x00FF); + buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF); + buf[5] = (fm_u8)((mask_or) & 0x00FF); + buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_MODIFY_BASIC_OP_SIZE + 2); +} + + +/* + * mt6620_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6620_off_2_longANA_1(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //A01 Turn on the bandgap and central biasing core + pkt_size += fm_bop_write(0x01, 0x4A00, &buf[pkt_size], buf_size - pkt_size);//wr 1 4A00 + pkt_size += fm_bop_udelay(30, &buf[pkt_size], buf_size - pkt_size);//delay 30 + pkt_size += fm_bop_write(0x01, 0x6A00, &buf[pkt_size], buf_size - pkt_size);//wr 1 6A00 + pkt_size += fm_bop_udelay(50, &buf[pkt_size], buf_size - pkt_size);//delay 50 + //A02 Initialise the LDO's Output + pkt_size += fm_bop_write(0x02, 0x299C, &buf[pkt_size], buf_size - pkt_size);//wr 2 299C + //A03 Enable RX, ADC and ADPLL LDO + pkt_size += fm_bop_write(0x01, 0x6B82, &buf[pkt_size], buf_size - pkt_size);//wr 1 6B82 + //A04 Update FMRF optimized register settings + pkt_size += fm_bop_write(0x04, 0x0142, &buf[pkt_size], buf_size - pkt_size);//wr 4 0142 + pkt_size += fm_bop_write(0x05, 0x00E7, &buf[pkt_size], buf_size - pkt_size);//wr 5 00E7 + pkt_size += fm_bop_write(0x0A, 0x0060, &buf[pkt_size], buf_size - pkt_size);//wr a 0060 + pkt_size += fm_bop_write(0x0C, 0xA88C, &buf[pkt_size], buf_size - pkt_size);//wr c A88C + pkt_size += fm_bop_write(0x0D, 0x0888, &buf[pkt_size], buf_size - pkt_size);//wr d 0888 + pkt_size += fm_bop_write(0x10, 0x1E8D, &buf[pkt_size], buf_size - pkt_size);//wr 10 1E8D + pkt_size += fm_bop_write(0x27, 0x0005, &buf[pkt_size], buf_size - pkt_size);//wr 27 0005 + pkt_size += fm_bop_write(0x0E, 0x0040, &buf[pkt_size], buf_size - pkt_size);//wr e 0040 + pkt_size += fm_bop_write(0x03, 0x50F0, &buf[pkt_size], buf_size - pkt_size);//wr 3 50f0 + pkt_size += fm_bop_write(0x3F, 0xAD06, &buf[pkt_size], buf_size - pkt_size);//wr 3f AD06 + pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size);//wr 3e 3280 + pkt_size += fm_bop_write(0x06, 0x0124, &buf[pkt_size], buf_size - pkt_size);//wr 6 0124 + pkt_size += fm_bop_write(0x08, 0x15B8, &buf[pkt_size], buf_size - pkt_size);//wr 8 15B8 + //A05 Enable RX related blocks + pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 28 0000 + pkt_size += fm_bop_write(0x00, 0x0166, &buf[pkt_size], buf_size - pkt_size);//wr 0 0166 + pkt_size += fm_bop_write(0x3A, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 3a 0004 + pkt_size += fm_bop_write(0x37, 0x2590, &buf[pkt_size], buf_size - pkt_size);//wr 37 2590 + // FM ADPLL Power Up + // () for 16.384M mode, otherwise 15.36M + pkt_size += fm_bop_write(0x25, 0x040F, &buf[pkt_size], buf_size - pkt_size);//wr 25 040f + pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size);//wr 20 2720 + //XHC, 2011/03/18, [wr 22 9980->6680] + pkt_size += fm_bop_write(0x22, 0x6680, &buf[pkt_size], buf_size - pkt_size);//wr 22 9980 + pkt_size += fm_bop_write(0x25, 0x080F, &buf[pkt_size], buf_size - pkt_size);//wr 25 080f + pkt_size += fm_bop_write(0x1E, 0x0863, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0863(0A63) + pkt_size += fm_bop_udelay(5000, &buf[pkt_size], buf_size - pkt_size);//delay 5000 + pkt_size += fm_bop_write(0x1E, 0x0865, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0865 (0A65) + pkt_size += fm_bop_udelay(5000, &buf[pkt_size], buf_size - pkt_size);//delay 5000 + pkt_size += fm_bop_write(0x1E, 0x0871, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0871 (0A71) + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_off_2_longANA_2(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100000 + pkt_size += fm_bop_write(0x2A, 0x1026, &buf[pkt_size], buf_size - pkt_size);//wr 2a 1026 + // FM RC Calibration + pkt_size += fm_bop_write(0x00, 0x01E6, &buf[pkt_size], buf_size - pkt_size);//wr 0 01E6 + pkt_size += fm_bop_udelay(1, &buf[pkt_size], buf_size - pkt_size);//delay 1 + pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0094 + pkt_size += fm_bop_write(0x1B, 0x0095, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0095 + pkt_size += fm_bop_udelay(200, &buf[pkt_size], buf_size - pkt_size);//delay 200 + pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0094 + pkt_size += fm_bop_write(0x00, 0x0166, &buf[pkt_size], buf_size - pkt_size);//wr 0 0166 + // FM VCO Enable + pkt_size += fm_bop_write(0x01, 0x6B8A, &buf[pkt_size], buf_size - pkt_size);//wr 1 6B8A + pkt_size += fm_bop_udelay(1, &buf[pkt_size], buf_size - pkt_size);//delay 1 + pkt_size += fm_bop_write(0x00, 0xC166, &buf[pkt_size], buf_size - pkt_size);//wr 0 C166 + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3000 + pkt_size += fm_bop_write(0x00, 0xF166, &buf[pkt_size], buf_size - pkt_size);//wr 0 F166 + pkt_size += fm_bop_write(0x09, 0x2964, &buf[pkt_size], buf_size - pkt_size);//wr 9 2964 + // FM RFDIG settings + pkt_size += fm_bop_write(0x2E, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 2e 8 + pkt_size += fm_bop_write(0x2B, 0x0064, &buf[pkt_size], buf_size - pkt_size);//wr 2b 64 + pkt_size += fm_bop_write(0x2C, 0x0032, &buf[pkt_size], buf_size - pkt_size);//wr 2c 32 + pkt_size += fm_bop_write(0x11, 0x17d4, &buf[pkt_size], buf_size - pkt_size);//wr 11 17d4 + //Update dynamic subband switching setting, XHC 2011/05/17 + pkt_size += fm_bop_write(0x13, 0xFA00, &buf[pkt_size], buf_size - pkt_size);//wr 13 FA00 + pkt_size += fm_bop_write(0x14, 0x0580, &buf[pkt_size], buf_size - pkt_size);//wr 14 0580 + pkt_size += fm_bop_write(0x15, 0xFA80, &buf[pkt_size], buf_size - pkt_size);//wr 15 FA80 + pkt_size += fm_bop_write(0x16, 0x0580, &buf[pkt_size], buf_size - pkt_size);//wr 16 0580 + pkt_size += fm_bop_write(0x33, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 33 0008 + // FM DCOC Calibration + pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 64 1 + pkt_size += fm_bop_write(0x63, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 63 20 + pkt_size += fm_bop_write(0x9C, 0x0044, &buf[pkt_size], buf_size - pkt_size);//wr 9C 0044 + //pkt_size += fm_bop_write(0x6B, 0x0100, &buf[pkt_size], buf_size - pkt_size);//"Disable other interrupts except for STC_DONE(dependent on interrupt output source selection)" + pkt_size += fm_bop_write(0x0F, 0x1A08, &buf[pkt_size], buf_size - pkt_size);//wr F 1A08 + pkt_size += fm_bop_write(0x63, 0x0021, &buf[pkt_size], buf_size - pkt_size);//wr 63 21 + pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &buf[pkt_size], buf_size - pkt_size);//Poll fm_intr_stc_done (69H D0) = 1 + pkt_size += fm_bop_write(0x69, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 69 1 + pkt_size += fm_bop_write(0x63, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 0 + pkt_size += fm_bop_rd_until(0x6F, 0x0001, 0x0000, &buf[pkt_size], buf_size - pkt_size);//Poll stc_done (6FH D0)= 0 + // Others + pkt_size += fm_bop_write(0x00, 0xF167, &buf[pkt_size], buf_size - pkt_size);//wr 0 F167 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_rx_digital_init(fm_u8 *tx_buf, fm_s32 tx_buf_size) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + // fm_rgf_maincon + //rd 62 + pkt_size += fm_bop_write(0x65, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 0 + pkt_size += fm_bop_write(0x64, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 64 1 + pkt_size += fm_bop_write(0x63, 0x0480, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 63 480 + pkt_size += fm_bop_write(0x6D, 0x1AB2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6d 1ab2 + pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100 + pkt_size += fm_bop_write(0x68, 0xE100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E100 + pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000 + pkt_size += fm_bop_write(0x68, 0xE000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E000 + // fm_rgf_dac + pkt_size += fm_bop_write(0x9C, 0xab48, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c ab48 + pkt_size += fm_bop_write(0x9E, 0x000C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9e c + pkt_size += fm_bop_write(0x71, 0x807f, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 71 807f + pkt_size += fm_bop_write(0x72, 0x878f, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 72 878f + //XHC, 2011/04/29 update 0x73 form 0x07C3 to 0x07C1 speed up I/Q calibration + pkt_size += fm_bop_write(0x73, 0x07c1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 73 7c3 + // fm_rgf_front + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 + pkt_size += fm_bop_write(0xCB, 0x00B0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cb b0 + //XHC, 2011/05/06 FM RSSI config +// pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG & 0x03FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e0 a301 +// pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (FMR_CQI_TH & 0x00FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e1 D0~D7, PAMD TH + //Run,2013/01 smt scan, ignore this + pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (0x0301 & 0x03FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e0 a301 + pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (0x00E9 & 0x00FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e1 D0~D7, PAMD TH + //XHC, 2011/04/15 update search MR threshold +// pkt_size += fm_bop_write(0xE3, FMR_MR_TH, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 1B0 + //Run,2013/01 smt scan, ignore this + pkt_size += fm_bop_write(0xE3, 0x01BD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 1B0 + pkt_size += fm_bop_write(0xE4, 0x008F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e4 8f + pkt_size += fm_bop_write(0xCC, 0x0488, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cc 488 + pkt_size += fm_bop_write(0xD6, 0x036A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d6 36a + pkt_size += fm_bop_write(0xD7, 0x836a, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d7 836a + pkt_size += fm_bop_write(0xDD, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dd 80 + pkt_size += fm_bop_write(0xB0, 0xcd00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b0 cd00 + //XHC, 2011/03/18 Update AFC gain[wr 96 41E2->4000][wr 97 049A->021F] + //[wr 98 0B66->0D00][wr 99 0E1E->0E7F][wr D0 8233->8192][wr D1 20BC->2086] + //[wr 90 03FF->0192][wr 91 01BE->0086][wr 92 03FF->0192][wr 93 0354->0086] + //[wr 94 03FF->0192][wr 95 0354->0086][wr 52 17F3] + pkt_size += fm_bop_write(0x96, 0x4000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 96 41E2 + pkt_size += fm_bop_write(0x97, 0x021F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 97 049A + pkt_size += fm_bop_write(0x98, 0x0D00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 98 0B66 + pkt_size += fm_bop_write(0x99, 0x0E7F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 99 0E1E + pkt_size += fm_bop_write(0xD0, 0x8192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr D0 8233 + pkt_size += fm_bop_write(0xD1, 0x2086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr D1 20BC + pkt_size += fm_bop_write(0x90, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 90 03ff + pkt_size += fm_bop_write(0x91, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 91 01BE + pkt_size += fm_bop_write(0x92, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 92 03FF + pkt_size += fm_bop_write(0x93, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 93 0354 + pkt_size += fm_bop_write(0x94, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 94 03FF + pkt_size += fm_bop_write(0x95, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 95 0354 + pkt_size += fm_bop_write(0x52, 0x17F3, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 95 0354 + // fm_rgf_fmx + pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1 + pkt_size += fm_bop_write(0xDE, 0x3388, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr de 3388 + pkt_size += fm_bop_write(0xC2, 0x0180, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c2 180 + pkt_size += fm_bop_write(0xC3, 0x0180, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c3 180 + pkt_size += fm_bop_write(0xDB, 0x0181, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr db 181 + pkt_size += fm_bop_write(0xDC, 0x0184, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dc 184 + pkt_size += fm_bop_write(0xA2, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 3c0 + pkt_size += fm_bop_write(0xA3, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a3 3c0 + pkt_size += fm_bop_write(0xA4, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a4 3c0 + pkt_size += fm_bop_write(0xA5, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a5 3c0 + pkt_size += fm_bop_write(0xA6, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a6 3c0 + pkt_size += fm_bop_write(0xA7, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a7 3c0 + pkt_size += fm_bop_write(0xE3, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 280 + pkt_size += fm_bop_write(0xE4, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e4 280 + pkt_size += fm_bop_write(0xE5, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e5 280 + pkt_size += fm_bop_write(0xE6, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e6 26c + pkt_size += fm_bop_write(0xE7, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e7 26c + pkt_size += fm_bop_write(0xEA, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ea 26c + pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000 + pkt_size += fm_bop_write(0xB6, 0x03FC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b6 3fc + pkt_size += fm_bop_write(0xB7, 0x02C1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b7 2c1 + pkt_size += fm_bop_write(0xA8, 0x0820, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 820 + pkt_size += fm_bop_write(0xAC, 0x065E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ac 65e + pkt_size += fm_bop_write(0xAD, 0x09AD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ad 9ad + pkt_size += fm_bop_write(0xAE, 0x0CF8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ae cf8 + pkt_size += fm_bop_write(0xAF, 0x0302, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr af 302 + pkt_size += fm_bop_write(0xB0, 0x04A6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b0 4a6 + pkt_size += fm_bop_write(0xB1, 0x062C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b1 62c + pkt_size += fm_bop_write(0xEC, 0x014A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ec 14a + pkt_size += fm_bop_write(0xC8, 0x0232, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c8 232 + pkt_size += fm_bop_write(0xC7, 0x0184, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c7 0184 + pkt_size += fm_bop_write(0xD8, 0x00E8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d8 0e8 + pkt_size += fm_bop_write(0xFB, 0x051F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fb 51f + pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000 + //XHC,2011/03/18 [wr C9 01F0][wr CA 0250][wr D4 2657] + pkt_size += fm_bop_write(0xC9, 0x01F0, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0xCA, 0x0250, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0xD4, 0x2657, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0x9F, 0x0002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 2 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0xFF80, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff80 + pkt_size += fm_bop_write(0xA8, 0x0061, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 61 + pkt_size += fm_bop_write(0xA8, 0xFF22, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff22 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 100 + pkt_size += fm_bop_write(0xA8, 0x009A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 9a + pkt_size += fm_bop_write(0xA8, 0xFF80, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff80 + pkt_size += fm_bop_write(0xA8, 0x0140, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 140 + pkt_size += fm_bop_write(0xA8, 0xFF42, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff42 + pkt_size += fm_bop_write(0xA8, 0xFFE0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ffe0 + pkt_size += fm_bop_write(0xA8, 0x0114, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 114 + pkt_size += fm_bop_write(0xA8, 0xFF4E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff4e + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x003E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 3e + pkt_size += fm_bop_write(0xA8, 0xFF6E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff6e + pkt_size += fm_bop_write(0xA8, 0x0087, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 87 + pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0xFEDC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 fedc + pkt_size += fm_bop_write(0xA8, 0x0015, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 15 + pkt_size += fm_bop_write(0xA8, 0x00CF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 cf + pkt_size += fm_bop_write(0xA8, 0xFF6B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff6b + pkt_size += fm_bop_write(0xA8, 0x0164, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 164 + pkt_size += fm_bop_write(0xA8, 0x002B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 2b + pkt_size += fm_bop_write(0xA8, 0xFF7E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff7e + pkt_size += fm_bop_write(0xA8, 0x0065, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 65 + pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000 + pkt_size += fm_bop_write(0x9F, 0x0002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 2 + pkt_size += fm_bop_write(0xA9, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 0 + pkt_size += fm_bop_write(0xA9, 0xFFEE, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffee + pkt_size += fm_bop_write(0xA9, 0xFF81, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ff81 + //XHC,2011/03/18 [wr A9 FFC3] + pkt_size += fm_bop_write(0xA9, 0xFFC3, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0xA9, 0x0022, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 22 + pkt_size += fm_bop_write(0xA9, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 0 + pkt_size += fm_bop_write(0xA9, 0xFFCC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffcc + pkt_size += fm_bop_write(0xA9, 0x0023, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 23 + pkt_size += fm_bop_write(0xA9, 0xFFDA, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffda + pkt_size += fm_bop_write(0xA9, 0xFFF7, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 fff7 + pkt_size += fm_bop_udelay(10, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10 + pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1 + pkt_size += fm_bop_write(0xD3, 0x250b, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d3 250b + pkt_size += fm_bop_write(0xBB, 0x2320, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bb 2320 + pkt_size += fm_bop_write(0xD0, 0x02f8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d0 02f8 + pkt_size += fm_bop_write(0xEC, 0x019a, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ec 19a + pkt_size += fm_bop_write(0xFE, 0x2140, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe 2140 + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 + // fm_rgf_rds + pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 3 + pkt_size += fm_bop_write(0xBD, 0x37EB, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bd 37eb + pkt_size += fm_bop_write(0xBC, 0x0404, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bc 404 + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6620_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + + // fm_rgf_maincon + //rd 62 + pkt_size += fm_bop_write(0x65, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 65 0 + pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 64 1 + pkt_size += fm_bop_write(0x63, 0x0480, &buf[pkt_size], buf_size - pkt_size);//wr 63 480 + pkt_size += fm_bop_write(0x6D, 0x1AB2, &buf[pkt_size], buf_size - pkt_size);//wr 6d 1ab2 + pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6b 2100 + pkt_size += fm_bop_write(0x68, 0xE100, &buf[pkt_size], buf_size - pkt_size);//wr 68 E100 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x68, 0xE000, &buf[pkt_size], buf_size - pkt_size);//wr 68 E000 + // fm_rgf_dac + pkt_size += fm_bop_write(0x9C, 0xab48, &buf[pkt_size], buf_size - pkt_size);//wr 9c ab48 + pkt_size += fm_bop_write(0x9E, 0x000C, &buf[pkt_size], buf_size - pkt_size);//wr 9e c + pkt_size += fm_bop_write(0x71, 0x807f, &buf[pkt_size], buf_size - pkt_size);//wr 71 807f + pkt_size += fm_bop_write(0x72, 0x878f, &buf[pkt_size], buf_size - pkt_size);//wr 72 878f + //XHC, 2011/04/29 update 0x73 form 0x07C3 to 0x07C1 speed up I/Q calibration + pkt_size += fm_bop_write(0x73, 0x07c1, &buf[pkt_size], buf_size - pkt_size);//wr 73 7c3 + // fm_rgf_front + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0 + pkt_size += fm_bop_write(0xCB, 0x00B0, &buf[pkt_size], buf_size - pkt_size);//wr cb b0 + //XHC, 2011/05/06 FM RSSI config + pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG_MT6620 & 0x03FF)), &buf[pkt_size], buf_size - pkt_size);//wr e0 a301 + pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (FMR_CQI_TH_MT6620 & 0x00FF)), &buf[pkt_size], buf_size - pkt_size);//wr e1 D0~D7, PAMD TH + //XHC, 2011/04/15 update search MR threshold + pkt_size += fm_bop_write(0xE3, FMR_MR_TH_MT6620, &buf[pkt_size], buf_size - pkt_size);//wr e3 1B0 + pkt_size += fm_bop_write(0xE4, 0x008F, &buf[pkt_size], buf_size - pkt_size);//wr e4 8f + pkt_size += fm_bop_write(0xCC, 0x0488, &buf[pkt_size], buf_size - pkt_size);//wr cc 488 + pkt_size += fm_bop_write(0xD6, 0x036A, &buf[pkt_size], buf_size - pkt_size);//wr d6 36a + pkt_size += fm_bop_write(0xD7, 0x836a, &buf[pkt_size], buf_size - pkt_size);//wr d7 836a + pkt_size += fm_bop_write(0xDD, 0x0080, &buf[pkt_size], buf_size - pkt_size);//wr dd 80 + pkt_size += fm_bop_write(0xB0, 0xcd00, &buf[pkt_size], buf_size - pkt_size);//wr b0 cd00 + //XHC, 2011/03/18 Update AFC gain[wr 96 41E2->4000][wr 97 049A->021F] + //[wr 98 0B66->0D00][wr 99 0E1E->0E7F][wr D0 8233->8192][wr D1 20BC->2086] + //[wr 90 03FF->0192][wr 91 01BE->0086][wr 92 03FF->0192][wr 93 0354->0086] + //[wr 94 03FF->0192][wr 95 0354->0086][wr 52 17F3] + pkt_size += fm_bop_write(0x96, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 96 41E2 + pkt_size += fm_bop_write(0x97, 0x021F, &buf[pkt_size], buf_size - pkt_size);//wr 97 049A + pkt_size += fm_bop_write(0x98, 0x0D00, &buf[pkt_size], buf_size - pkt_size);//wr 98 0B66 + pkt_size += fm_bop_write(0x99, 0x0E7F, &buf[pkt_size], buf_size - pkt_size);//wr 99 0E1E + pkt_size += fm_bop_write(0xD0, 0x8192, &buf[pkt_size], buf_size - pkt_size);//wr D0 8233 + pkt_size += fm_bop_write(0xD1, 0x2086, &buf[pkt_size], buf_size - pkt_size);//wr D1 20BC + pkt_size += fm_bop_write(0x90, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 90 03ff + pkt_size += fm_bop_write(0x91, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 91 01BE + pkt_size += fm_bop_write(0x92, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 92 03FF + pkt_size += fm_bop_write(0x93, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 93 0354 + pkt_size += fm_bop_write(0x94, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 94 03FF + pkt_size += fm_bop_write(0x95, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 95 0354 + pkt_size += fm_bop_write(0x52, 0x17F3, &buf[pkt_size], buf_size - pkt_size);//wr 95 0354 + // fm_rgf_fmx + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1 + pkt_size += fm_bop_write(0xDE, 0x3388, &buf[pkt_size], buf_size - pkt_size);//wr de 3388 + pkt_size += fm_bop_write(0xC2, 0x0180, &buf[pkt_size], buf_size - pkt_size);//wr c2 180 + pkt_size += fm_bop_write(0xC3, 0x0180, &buf[pkt_size], buf_size - pkt_size);//wr c3 180 + pkt_size += fm_bop_write(0xDB, 0x0181, &buf[pkt_size], buf_size - pkt_size);//wr db 181 + pkt_size += fm_bop_write(0xDC, 0x0184, &buf[pkt_size], buf_size - pkt_size);//wr dc 184 + pkt_size += fm_bop_write(0xA2, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a2 3c0 + pkt_size += fm_bop_write(0xA3, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a3 3c0 + pkt_size += fm_bop_write(0xA4, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a4 3c0 + pkt_size += fm_bop_write(0xA5, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a5 3c0 + pkt_size += fm_bop_write(0xA6, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a6 3c0 + pkt_size += fm_bop_write(0xA7, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a7 3c0 + pkt_size += fm_bop_write(0xE3, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e3 280 + pkt_size += fm_bop_write(0xE4, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e4 280 + pkt_size += fm_bop_write(0xE5, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e5 280 + pkt_size += fm_bop_write(0xE6, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr e6 26c + pkt_size += fm_bop_write(0xE7, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr e7 26c + pkt_size += fm_bop_write(0xEA, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr ea 26c + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1000 + pkt_size += fm_bop_write(0xB6, 0x03FC, &buf[pkt_size], buf_size - pkt_size);//wr b6 3fc + pkt_size += fm_bop_write(0xB7, 0x02C1, &buf[pkt_size], buf_size - pkt_size);//wr b7 2c1 + pkt_size += fm_bop_write(0xA8, 0x0820, &buf[pkt_size], buf_size - pkt_size);//wr a8 820 + pkt_size += fm_bop_write(0xAC, 0x065E, &buf[pkt_size], buf_size - pkt_size);//wr ac 65e + pkt_size += fm_bop_write(0xAD, 0x09AD, &buf[pkt_size], buf_size - pkt_size);//wr ad 9ad + pkt_size += fm_bop_write(0xAE, 0x0CF8, &buf[pkt_size], buf_size - pkt_size);//wr ae cf8 + pkt_size += fm_bop_write(0xAF, 0x0302, &buf[pkt_size], buf_size - pkt_size);//wr af 302 + pkt_size += fm_bop_write(0xB0, 0x04A6, &buf[pkt_size], buf_size - pkt_size);//wr b0 4a6 + pkt_size += fm_bop_write(0xB1, 0x062C, &buf[pkt_size], buf_size - pkt_size);//wr b1 62c + pkt_size += fm_bop_write(0xEC, 0x014A, &buf[pkt_size], buf_size - pkt_size);//wr ec 14a + pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr c8 232 + pkt_size += fm_bop_write(0xC7, 0x0184, &buf[pkt_size], buf_size - pkt_size);//wr c7 0184 + pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr d8 0e8 + pkt_size += fm_bop_write(0xFB, 0x051F, &buf[pkt_size], buf_size - pkt_size);//wr fb 51f + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1000 + //XHC,2011/03/18 [wr C9 01F0][wr CA 0250][wr D4 2657] + pkt_size += fm_bop_write(0xC9, 0x01F0, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xCA, 0x0250, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xD4, 0x2657, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x9F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 9f 2 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0xFF80, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff80 + pkt_size += fm_bop_write(0xA8, 0x0061, &buf[pkt_size], buf_size - pkt_size);//wr a8 61 + pkt_size += fm_bop_write(0xA8, 0xFF22, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff22 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0100, &buf[pkt_size], buf_size - pkt_size);//wr a8 100 + pkt_size += fm_bop_write(0xA8, 0x009A, &buf[pkt_size], buf_size - pkt_size);//wr a8 9a + pkt_size += fm_bop_write(0xA8, 0xFF80, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff80 + pkt_size += fm_bop_write(0xA8, 0x0140, &buf[pkt_size], buf_size - pkt_size);//wr a8 140 + pkt_size += fm_bop_write(0xA8, 0xFF42, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff42 + pkt_size += fm_bop_write(0xA8, 0xFFE0, &buf[pkt_size], buf_size - pkt_size);//wr a8 ffe0 + pkt_size += fm_bop_write(0xA8, 0x0114, &buf[pkt_size], buf_size - pkt_size);//wr a8 114 + pkt_size += fm_bop_write(0xA8, 0xFF4E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff4e + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0x003E, &buf[pkt_size], buf_size - pkt_size);//wr a8 3e + pkt_size += fm_bop_write(0xA8, 0xFF6E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff6e + pkt_size += fm_bop_write(0xA8, 0x0087, &buf[pkt_size], buf_size - pkt_size);//wr a8 87 + pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0 + pkt_size += fm_bop_write(0xA8, 0xFEDC, &buf[pkt_size], buf_size - pkt_size);//wr a8 fedc + pkt_size += fm_bop_write(0xA8, 0x0015, &buf[pkt_size], buf_size - pkt_size);//wr a8 15 + pkt_size += fm_bop_write(0xA8, 0x00CF, &buf[pkt_size], buf_size - pkt_size);//wr a8 cf + pkt_size += fm_bop_write(0xA8, 0xFF6B, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff6b + pkt_size += fm_bop_write(0xA8, 0x0164, &buf[pkt_size], buf_size - pkt_size);//wr a8 164 + pkt_size += fm_bop_write(0xA8, 0x002B, &buf[pkt_size], buf_size - pkt_size);//wr a8 2b + pkt_size += fm_bop_write(0xA8, 0xFF7E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff7e + pkt_size += fm_bop_write(0xA8, 0x0065, &buf[pkt_size], buf_size - pkt_size);//wr a8 65 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_pwrup_digital_init_3(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x9F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 9f 2 + pkt_size += fm_bop_write(0xA9, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a9 0 + pkt_size += fm_bop_write(0xA9, 0xFFEE, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffee + pkt_size += fm_bop_write(0xA9, 0xFF81, &buf[pkt_size], buf_size - pkt_size);//wr a9 ff81 + //XHC,2011/03/18 [wr A9 FFC3] + pkt_size += fm_bop_write(0xA9, 0xFFC3, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xA9, 0x0022, &buf[pkt_size], buf_size - pkt_size);//wr a9 22 + pkt_size += fm_bop_write(0xA9, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a9 0 + pkt_size += fm_bop_write(0xA9, 0xFFCC, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffcc + pkt_size += fm_bop_write(0xA9, 0x0023, &buf[pkt_size], buf_size - pkt_size);//wr a9 23 + pkt_size += fm_bop_write(0xA9, 0xFFDA, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffda + pkt_size += fm_bop_write(0xA9, 0xFFF7, &buf[pkt_size], buf_size - pkt_size);//wr a9 fff7 + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size);//delay 10 + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1 + pkt_size += fm_bop_write(0xD3, 0x250b, &buf[pkt_size], buf_size - pkt_size);//wr d3 250b + pkt_size += fm_bop_write(0xBB, 0x2320, &buf[pkt_size], buf_size - pkt_size);//wr bb 2320 + pkt_size += fm_bop_write(0xD0, 0x02f8, &buf[pkt_size], buf_size - pkt_size);//wr d0 02f8 + pkt_size += fm_bop_write(0xEC, 0x019a, &buf[pkt_size], buf_size - pkt_size);//wr ec 19a + pkt_size += fm_bop_write(0xFE, 0x2140, &buf[pkt_size], buf_size - pkt_size);//wr fe 2140 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0 + // fm_rgf_rds + pkt_size += fm_bop_write(0x9F, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 9f 3 + pkt_size += fm_bop_write(0xBD, 0x37EB, &buf[pkt_size], buf_size - pkt_size);//wr bd 37eb + pkt_size += fm_bop_write(0xBC, 0x0404, &buf[pkt_size], buf_size - pkt_size);//wr bc 808 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6620_pwrdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Digital Modem Power Down + pkt_size += fm_bop_write(0x63, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 0 + pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round1 + pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round2 + pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round3 + pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round4 + //ADPLL Power Off Sequence + pkt_size += fm_bop_write(0x2A, 0x0022, &buf[pkt_size], buf_size - pkt_size);//wr 2a 22 + pkt_size += fm_bop_write(0x1E, 0x0860, &buf[pkt_size], buf_size - pkt_size);//wr 1E 0860 + pkt_size += fm_bop_write(0x20, 0x0720, &buf[pkt_size], buf_size - pkt_size);//wr 20 0720 + pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size);//wr 20 2720 + //ANALOG/RF Power Off Sequence + pkt_size += fm_bop_write(0x00, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 0 0 + pkt_size += fm_bop_write(0x01, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 1 0 + pkt_size += fm_bop_write(0x04, 0x0141, &buf[pkt_size], buf_size - pkt_size);//wr 4 0141 + pkt_size += fm_bop_write(0x09, 0x0964, &buf[pkt_size], buf_size - pkt_size);//wr 9 0964 + pkt_size += fm_bop_write(0x0C, 0x288C, &buf[pkt_size], buf_size - pkt_size);//wr c 288c + pkt_size += fm_bop_write(0x26, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 26 0004 + pkt_size += fm_bop_write(0x3A, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 3A 0000 + pkt_size += fm_bop_write(0x3B, 0x00C3, &buf[pkt_size], buf_size - pkt_size);//wr 3B 00C3 + pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size);//wr 3E 3280 + pkt_size += fm_bop_write(0x3F, 0x4E16, &buf[pkt_size], buf_size - pkt_size);//wr 3F 4E16 + pkt_size += fm_bop_write(0x41, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 41 0004 + //clear TX settings + pkt_size += fm_bop_write(0x12, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 12 0000 + pkt_size += fm_bop_write(0x47, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 47 0000 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6620_rampdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_RAMPDOWN_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(0x9C, 0xFF87, 0x0068, &buf[pkt_size], buf_size - pkt_size);//wr 9c[3] = 1, ramp down + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1 + pkt_size += fm_bop_write(0xC8, 0x0101, &buf[pkt_size], buf_size - pkt_size);//wr c8 101 + pkt_size += fm_bop_write(0xDD, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr dd 0 + pkt_size += fm_bop_write(0xD8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr d8 0 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0 + pkt_size += fm_bop_udelay(35000, &buf[pkt_size], buf_size - pkt_size);//delay 35000 + //disable interrupt before rampdown + pkt_size += fm_bop_write(0x6B, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6b 0000 + pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0, ramp down + pkt_size += fm_bop_rd_until(0x6f, 0x0001, 0x0000, &buf[pkt_size], buf_size - pkt_size);//Poll 6f[0] = b'0 + pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6b 2100 + //enable interrupt after rampdown + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} +#if 0//ramp down tx will do in tx tune flow +fm_s32 mt6620_rampdown_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_RAMPDOWN_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0500 + pkt_size += fm_bop_write(0x3A, 0x00FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a ff + pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1 + pkt_size += fm_bop_write(0x48, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 0 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} +#endif +/* + * mt6620_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +fm_s32 mt6620_tune_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 6400) * 2 /10; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20) + pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0001, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_tune_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } +/* + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 640) * 2 / 10; +*/ + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(0x9C, 0xFFF7, 0x0000, &buf[pkt_size], buf_size - pkt_size);// set 0x9C[3] = 0 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_tune_3(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } +/* + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 640) * 2 / 10; +*/ + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1 + pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232 + pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833 + pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_fast_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 6400) * 2 / 10; + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x63[3:0] = 0 + pkt_size += fm_bop_modify(0x6F, 0xFFFE, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x6F[0] = 0 + pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20) + //disable interrupt before rampdown + pkt_size += fm_bop_write(0x6B, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 0000 + pkt_size += fm_bop_modify(0x63, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x63[0] = 1 + pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll 69[0] = b'1 + pkt_size += fm_bop_modify(0x69, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x69[0] = 1 + pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100 + //enable interrupt after rampdown + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_full_cqi_req - execute request cqi info action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 7600 ~ 10800, freq array + * @cnt - channel count + * @type - request type, 1: a single channel; 2: multi channel; 3:multi channel with 100Khz step; 4: multi channel with 50Khz step + * + * return package size + */ + +fm_s32 mt6620_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_s32 cnt, fm_s32 type) +{ + fm_s32 pkt_size = 0; + + if(buf_size < TX_BUF_SIZE) + { + return (-1); + } + if (0 == fm_get_channel_space(freq)) + { + freq *= 10; + } + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SOFT_MUTE_TUNE_OPCODE; + pkt_size = 4; + + switch (type) { + case 1: + buf[pkt_size] = 0x0001; + pkt_size++; + buf[pkt_size] = (fm_u8)(freq & 0x00FF); + pkt_size++; + buf[pkt_size] = (fm_u8)((freq >> 8) & 0x00FF); + pkt_size++; + break; + default: + buf[pkt_size] = (fm_u16)type; + pkt_size++; + break; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; + +} + +// freq: 760 ~ 1080, 100KHz unit +fm_s32 mt6620_tune_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 6400) * 2 / 10; + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + //XHC, 2011/04/20, ramp down before tune + pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0500 + pkt_size += fm_bop_write(0x3A, 0x00FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a ff + pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1 + pkt_size += fm_bop_write(0x48, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 0 + //XHC, 2011/04/14 + pkt_size += fm_bop_modify(0x41, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x41[0] = 1 + //XHC, 2011/04/18 + pkt_size += fm_bop_modify(0x12, 0x7FFF, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x12[15] = 0 + //XHC, 2011/04/22, clear RTC compensation info + pkt_size += fm_bop_modify(0x47, 0x003F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x47[15:6] = 0 + pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = freq + pkt_size += fm_bop_write(0x26, 0x002C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 002C --> SCAL Related --> SCAL_EN and SCAL_GM_EN + pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us + pkt_size += fm_bop_write(0x26, 0x003C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 003C --> SCAL_BUF_EN + pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us + pkt_size += fm_bop_write(0x10, 0x1E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 1e8d + pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us + pkt_size += fm_bop_write(0x10, 0x9E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 9e8d + pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000us + pkt_size += fm_bop_write(0x26, 0x0024, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 0024 --> Turn off SCAL gm and BUF + pkt_size += fm_bop_write(0x65, 0x400F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 400f + pkt_size += fm_bop_write(0x48, 0x8000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 8000 + pkt_size += fm_bop_write(0x3B, 0x0420, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0420 + pkt_size += fm_bop_write(0x3A, 0x01FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a 1ff + //XHC, 2011/04/14 + //pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000us + //pkt_size += fm_bop_modify(0x41, 0xFFFE, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x41[0] = 0 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +// freq: 760 ~ 1080, 100KHz unit +fm_s32 mt6620_tune_txscan(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 6400) * 2 / 10; + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + //rampdown + //disable interrupt before rampdown + pkt_size += fm_bop_write(0x6B, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 0000 + pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 63[3:0] = 0, ramp down + pkt_size += fm_bop_rd_until(0x6f, 0x0001, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll 6f[0] = b'0 + pkt_size += fm_bop_modify(0x9C, 0xFFFF, 0x0008, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c[3] = 1, ramp down + pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100 + //enable interrupt after rampdown + + //set desired channel + pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20) + + //only for short antennal tune +#ifdef MT6620_FM_USE_SHORT_ANTENNA + pkt_size += fm_bop_write(0x28, 0x3800, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 3800 + pkt_size += fm_bop_write(0x03, 0x90F0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3 90f0 + pkt_size += fm_bop_write(0x2E, 0x0028, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2e 28 + pkt_size += fm_bop_write(0x2F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2f 0 + pkt_size += fm_bop_write(0x26, 0x003C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 3c + pkt_size += fm_bop_write(0x2E, 0x002C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2e 2c + pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wait 10ms + pkt_size += fm_bop_write(0x26, 0x0024, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 24 + pkt_size += fm_bop_write(0x28, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 00 +#endif + + //only for E1 +#ifdef MT6620E1 + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0 + pkt_size += fm_bop_write(0xAF, 0x2210, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr AF 2210 +#endif + + //mask STC_DONE interrupt, 6a(D0) 0 + //pkt_size += fm_bop_modify(0x6A, 0xFFFE, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size); + + //enable hardware are controlled tuning sequence + pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set rgf_tune (63H D0) =1 + + //check STC_DONE interrupt status flag + //pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll fm_intr_stc_done (69H D0) = 1 + + //write 1 clear the STC_DONE status flag + //pkt_size += fm_bop_modify(0x69, 0xFFFF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set stc_done (6FH D0) =1 + + //unmask STC_DONE interrupt, 6a(D0) 1 + //pkt_size += fm_bop_modify(0x6A, 0xFFFF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size); + + //only for E1 +#ifdef MT6620E1 + //pkt_size += fm_bop_write(0xAF, 0x7710, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr AF 7710 +#endif + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_seek - execute seek action, + * @buf - target buf + * @buf_size - buffer size + * @seekdir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6620_seek_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SEEK_OPCODE; + pkt_size = 4; + + //A1 Program seek direction, 0x66[10]: 0=seek up, 1=seek down + if (seekdir == 0) { + pkt_size += fm_bop_modify(0x66, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap + //A2 Program scan channel spacing, 0x66[14:12] step 50KHz:001/100KHz:010/200KHz:100 + if (space == 4) { + pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else { + pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } + + //0x66[9:0] freq upper bound + max_freq = (max_freq - 640) * 2; + pkt_size += fm_bop_modify(0x66, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + + //0x67[9:0] freq lower bound + min_freq = (min_freq - 640) * 2; + pkt_size += fm_bop_modify(0x67, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //A3 Enable hardware controlled seeking sequence + pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0002, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_seek_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SEEK_OPCODE; + pkt_size = 4; + + //A10 Set softmute to normal mode + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1 + pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232 + pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833 + pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6620_scan - execute scan action, + * @buf - target buf + * @buf_size - buffer size + * @scandir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6620_scan_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SCAN_OPCODE; + pkt_size = 4; + + //A1 Program seek direction, 0x66[10]: 0=seek up, 1=seek down + if (scandir == 0) { + pkt_size += fm_bop_modify(0x66, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap + //A2 Program scan channel spacing, 0x66[14:12] step 50KHz:001/100KHz:010/200KHz:100 + if (space == 4) { + pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else { + pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } + + //0x66[9:0] freq upper bound + max_freq = (max_freq - 640) * 2; + pkt_size += fm_bop_modify(0x66, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + + //0x67[9:0] freq lower bound + min_freq = (min_freq - 640) * 2; + pkt_size += fm_bop_modify(0x67, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //A3 Enable hardware controlled seeking sequence + pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0004, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_scan_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SCAN_OPCODE; + pkt_size = 4; + + //A10 Set softmute to normal mode + pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1 + pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232 + pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833 + pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8 + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_READ_OPCODE; + buf[2] = 0x01; + buf[3] = 0x00; + buf[4] = addr; + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + return 5; +} + +fm_s32 mt6620_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_WRITE_OPCODE; + buf[2] = 0x03; + buf[3] = 0x00; + buf[4] = addr; + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + return 7; +} + +fm_s32 mt6620_rds_rx_enable(fm_u8 *tx_buf, fm_s32 tx_buf_size) //IC version +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = RDS_RX_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0x9f 3 + pkt_size += fm_bop_write(0xCB, 0xE016, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0xcb e016 + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0x9f 0 + pkt_size += fm_bop_write(0x63, 0x0491, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0x63 491 + pkt_size += fm_bop_modify(0x6B, 0xFFFF, 0x2000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//Wr 0x6b [13] = 1 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6620_rds_rx_disable(fm_u8 *tx_buf, fm_s32 tx_buf_size) //IC version +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = RDS_RX_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(0x6B, 0xDFFF, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//Wr 0x6b [13] = 0 + pkt_size += fm_bop_write(0x63, 0x0481, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0x63 481 + + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +// TBD for IC +fm_s32 mt6620_rds_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt) +{ + fm_s32 pkt_size = 0; + fm_s32 i; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + if(other_rds_cnt > 29){ + return (-2); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = RDS_TX_OPCODE; + pkt_size = 4; + + //RDS Tx config + pkt_size += fm_bop_modify(0x65, 0xFFFF, 0x0010, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr 65[4] = b'1, enable RDS Tx + pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 3 + pkt_size += fm_bop_write(0xA2, 0x0005, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 5, repeat + PI_reg mode + pkt_size += fm_bop_write(0xA1, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a1 0 + //pkt_size += fm_bop_write(0xA0, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a0 1 + pkt_size += fm_bop_write(0xA4, pi, &tx_buf[pkt_size], tx_buf_size - pkt_size);//write PI to PI_reg + //program PS buf + pkt_size += fm_bop_rd_until(0xAA, 0x0001, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// rd until aa[0] = b'0, ptr in normal buf + //program normal buf, workaround that PS buf can't work while normal buf is empty + for(i = 0; i < 12; i++) + { + pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data + } + pkt_size += fm_bop_modify(0xA2, 0xFFFF, 0x0002, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[1] = b'1, mem_addr mode + for(i = 0; i < 12; i++) + { + pkt_size += fm_bop_write(0xA7, (0x0063+i), &tx_buf[pkt_size], tx_buf_size - pkt_size);//a7 = mem_addr + pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data + } + pkt_size += fm_bop_modify(0xA2, 0xFFFF, 0x0010, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[4] = b'1, switch to ps buf + //program normal buf + pkt_size += fm_bop_rd_until(0xAA, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// rd until aa[0] = b'1, ptr in ps buf + pkt_size += fm_bop_modify(0xA2, 0xFFFD, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[1] = b'0, h/w addr mode + for(i = 0; i < 12; i++) + { + pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data + } + for(i = 0; i < (other_rds_cnt * 3); i++) + { + pkt_size += fm_bop_write(0xA8, other_rds[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data + } + pkt_size += fm_bop_modify(0xA2, 0xFFEF, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[4] = b'0, switch to normal buf + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +// TBD for IC +fm_s32 mt6620_off_2_tx_shortANA(fm_u8 *tx_buf, fm_s32 tx_buf_size) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_write(0x01, 0x4A00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 4A00 --> Turn on Central Bias + FC + pkt_size += fm_bop_udelay(30, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 30 + pkt_size += fm_bop_write(0x01, 0x6A00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6A00 --> Turn off FC + pkt_size += fm_bop_udelay(50, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 50 + pkt_size += fm_bop_write(0x02, 0x299C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2 299C --> Set the LDOs Output Voltages + pkt_size += fm_bop_write(0x01, 0x6B82, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6B82 --> Turn on DCO, RX and ADDA LDO + pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3B 0500 --> Turn on PA LDO --> LDO PA = 2.5V [0000 010x xxx0 000] {xxxx} - 0001 = 2.5V + pkt_size += fm_bop_write(0x04, 0x0548, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4 0548 --> Set the RX LDO to Low Power Mode + TR Switch Off + pkt_size += fm_bop_write(0x37, 0x2000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 37 2000 --> Set the Short Antenna Bias + pkt_size += fm_bop_write(0x42, 0xC002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 42 C002 --> Set the Short Antenna Bias + pkt_size += fm_bop_write(0x0A, 0x0060, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr A 0060 --> Update AFCDAC LPF Setting + pkt_size += fm_bop_write(0x0E, 0x0040, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr E 0040 --> Update SX_VDC_CBANK + pkt_size += fm_bop_write(0x0C, 0xA88C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c A88C + pkt_size += fm_bop_write(0x10, 0x1E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 1e8d + pkt_size += fm_bop_write(0x27, 0x0005, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 27 0005 --> Update ACAL and Enable RMS_DET + pkt_size += fm_bop_write(0x11, 0x07D8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 11 07D8 --> Set VCO_DIVRST_N = 0 + pkt_size += fm_bop_write(0x41, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 41 0003 --> Set TX_FVCO_EN = 1 and FVCO_SEL=1 + pkt_size += fm_bop_write(0x08, 0x25B8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 8 25b8 --> ADC = TX Mode (AU_ADC) + pkt_size += fm_bop_write(0x09, 0x2964, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9 2964 --> ADC DWA ON + pkt_size += fm_bop_write(0x3F, 0xAD86, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3F AD86 --> TX DAc RX_TX_SEL = TX MOde + pkt_size += fm_bop_write(0x3A, 0x01EF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3A 01EF --> Turn on TX Chain [PA+D2S+HRM+AUPGA+TXDAC+LODIV] + pkt_size += fm_bop_write(0x3E, 0x3181, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3E 3181 --> TX LPF EN + CSEL from RCCAL + pkt_size += fm_bop_write(0x00, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 0100 --> Turn on SDADC + pkt_size += fm_bop_write(0x37, 0x2000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 37 2000 --> Control Signal for DAC_CK output clock gate + //FM ADPLL Power Up + pkt_size += fm_bop_write(0x25, 0x040F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 25 040f --> Turn off DIG_CK_EN + pkt_size += fm_bop_write(0x20, 0x2720, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 20 2720 --> Turn on ADPLL 2320 CW32 + //XHC,2011/03/18, [wr 22 9980-> 6680] + pkt_size += fm_bop_write(0x22, 0x6680, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 22 9980 --> Update DLF Gain + pkt_size += fm_bop_write(0x25, 0x080F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 25 080f --> Update I_CODE_CCAL + ADC_CK_EN + 32KCLKPLL_EN 0803 CW37 + pkt_size += fm_bop_write(0x1E, 0x0863, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0863 --> Turn on DCO + CAL_COARSE_EN + pkt_size += fm_bop_udelay(5000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 5000 + pkt_size += fm_bop_write(0x1E, 0x0865, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0865 --> Change the CAL_COARSE to CAL_FINE + pkt_size += fm_bop_udelay(5000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 5000 + pkt_size += fm_bop_write(0x1E, 0x0871, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0871 --> Off the CAL_COARSE and CAL_FINE + Turn on PLL + pkt_size += fm_bop_udelay(100000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 100000 + pkt_size += fm_bop_write(0x2A, 0x1026, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2a 1022 --> Enable TOP_CG + //FM RC Calibration + pkt_size += fm_bop_write(0x00, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 0080 --> RCCAL + pkt_size += fm_bop_udelay(1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000 + pkt_size += fm_bop_write(0x1B, 0x0094, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0094 --> Update RCCAL Target Count + pkt_size += fm_bop_write(0x1B, 0x0095, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0095 --> Start RCCAL + pkt_size += fm_bop_udelay(200, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000 + pkt_size += fm_bop_write(0x1B, 0x0094, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0094 --> Off RCCAL + pkt_size += fm_bop_write(0x00, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 0100 --> Turn off RCCAL Analog Block + //FM VCO Enable + pkt_size += fm_bop_write(0x01, 0x6B8A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6B8A --> Turn on VCO LDO + pkt_size += fm_bop_udelay(1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000 + pkt_size += fm_bop_write(0x00, 0xC100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 C100 --> Turn on VCO, AFCDAC + pkt_size += fm_bop_write(0x0C, 0xB88C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c B88c --> Turn on Const gm + pkt_size += fm_bop_udelay(3000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 3000 + pkt_size += fm_bop_write(0x3A, 0x01FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3A 01FF --> Enable TX Divider + //Short Antenna Setting + pkt_size += fm_bop_write(0x42, 0xF002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 42 F002 --> MSB of HRM_Gain <5> ****>> For Max Pout + pkt_size += fm_bop_write(0x3C, 0xABE9, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3C ABE9 --> Max HRM Gain<4:0> - xxxxx [1010 10xx xxx0 1001] + pkt_size += fm_bop_write(0x3D, 0x027E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3D 027E --> Max PA Gain<4:0> - [0000 0010 0xxx xx10] + pkt_size += fm_bop_write(0x33, 0x0008, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 33 0008 --> Use old VCO calibration routine to save calibration time + pkt_size += fm_bop_write(0x28, 0xFFFF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 FFFF + pkt_size += fm_bop_write(0x2E, 0x0020, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2E 0020 --> Turn on SCAL_HWTRIG_DIS --> VCO CAL and SCAL are done separately + pkt_size += fm_bop_write(0x2F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2F 0000 --> Disable Capbank manual enter mode [4A40 previously] + pkt_size += fm_bop_write(0x44, 0x006E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 44 6e + pkt_size += fm_bop_write(0x46, 0xDC22, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 46 DC22 + pkt_size += fm_bop_write(0x49, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 49 80 + pkt_size += fm_bop_write(0x4A, 0x0004, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4A 4 + pkt_size += fm_bop_write(0x4B, 0x0040, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4B 40 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + +// TBD for IC +fm_s32 mt6620_dig_init(fm_u8 *tx_buf, fm_s32 tx_buf_size) +{ + fm_s32 pkt_size = 0; + + if(tx_buf_size < TX_BUF_SIZE){ + return (-1); + } + + tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE; + tx_buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + +//fm_rgf_maincon + pkt_size += fm_bop_write(0x64, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 64 0 + pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1 + pkt_size += fm_bop_write(0x68, 0xE100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E100 + pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000 + pkt_size += fm_bop_write(0x68, 0xE000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E000 +//fm_rgf_dac + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0 + pkt_size += fm_bop_write(0x9E, 0x001C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9E 1C + pkt_size += fm_bop_write(0x9C, 0xA540, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c A540 +//fm_rgf_front + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 --> start rgf_front + pkt_size += fm_bop_write(0xB8, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b8 1 + pkt_size += fm_bop_write(0xAB, 0x39B6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ab 39b6 + pkt_size += fm_bop_write(0xAC, 0x3C3E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ac 3c3e + pkt_size += fm_bop_write(0xAD, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ad 0 + pkt_size += fm_bop_write(0xAE, 0x03C2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ae 3c2 + pkt_size += fm_bop_write(0xAF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr af 1 + pkt_size += fm_bop_write(0xB1, 0x623D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b1 623d + pkt_size += fm_bop_write(0xF4, 0x0020, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr f4 20 + pkt_size += fm_bop_write(0xF5, 0xBF16, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr f5 bf16 + pkt_size += fm_bop_write(0xB9, 0x0050, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b9 0050 + pkt_size += fm_bop_write(0xBA, 0x00C3, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ba 00c3 + pkt_size += fm_bop_write(0xBB, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bb 0 + pkt_size += fm_bop_write(0xBC, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bc 0 + pkt_size += fm_bop_write(0xBD, 0x0056, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bd 56 + pkt_size += fm_bop_write(0xBE, 0x0089, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr be 89 + pkt_size += fm_bop_write(0xBF, 0x004C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bf 4c + pkt_size += fm_bop_write(0xC0, 0x0171, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c0 171 + pkt_size += fm_bop_write(0xC1, 0x002B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c1 2b + pkt_size += fm_bop_write(0xC2, 0x001F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c2 1f + pkt_size += fm_bop_write(0xC3, 0x0066, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c3 66 + pkt_size += fm_bop_write(0xC4, 0x00F6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c4 f6 + pkt_size += fm_bop_write(0xC5, 0x0066, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c5 66 + pkt_size += fm_bop_write(0xC6, 0x001F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c6 1f + pkt_size += fm_bop_write(0xC7, 0x0007, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c7 7 + pkt_size += fm_bop_write(0xFE, 0x0039, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe 39 + pkt_size += fm_bop_write(0xFF, 0x3907, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ff 3907 +//fm_rgf_fmx + pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1 --> start rgf_outer + pkt_size += fm_bop_write(0xC0, 0x076C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c0 76c + pkt_size += fm_bop_write(0xB7, 0x0004, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b7 4 + pkt_size += fm_bop_write(0xD8, 0x006A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d8 6a + pkt_size += fm_bop_write(0xC8, 0x2828, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c8 2828 + pkt_size += fm_bop_write(0xCE, 0x0090, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ce 90 + pkt_size += fm_bop_write(0xFE, 0x000F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe f + pkt_size += fm_bop_write(0xA2, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 100 + pkt_size += fm_bop_write(0xA3, 0x0111, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a3 111 + pkt_size += fm_bop_write(0xA4, 0x0122, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a4 122 + pkt_size += fm_bop_write(0xA5, 0x0135, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a5 135 + pkt_size += fm_bop_write(0xA6, 0x0149, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a6 149 + pkt_size += fm_bop_write(0xA7, 0x015E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a7 15e + pkt_size += fm_bop_write(0xDB, 0x0174, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr db 174 + pkt_size += fm_bop_write(0xDC, 0x018D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dc 18d + pkt_size += fm_bop_write(0xC9, 0x01A6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c9 1a6 + pkt_size += fm_bop_write(0xCA, 0x01C1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ca 1c1 + pkt_size += fm_bop_write(0xCB, 0x01DE, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cb 1de + pkt_size += fm_bop_write(0xCC, 0x01FD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cc 1fd + pkt_size += fm_bop_write(0xD4, 0x2657, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d4 2657 + pkt_size += fm_bop_write(0xA0, 0x85B2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a0 85b2 + pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 + + tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF); + tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF); + + return pkt_size; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c new file mode 100755 index 000000000000..1b16332716a1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c @@ -0,0 +1,357 @@ +/* fm_config.c + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_patch.h" +#include "fm_config.h" +//#include "fm_cust_cfg.h" +#include "mt6620_fm_cust_cfg.h" + +fm_cust_cfg mt6620_fm_config; +//static fm_s32 fm_index = 0; + +static fm_s32 MT6620fm_cust_config_print(fm_cust_cfg *cfg) +{ + // fm_s32 i; + + WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_l:\t%d\n", cfg->rx_cfg.long_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_s:\t%d\n", cfg->rx_cfg.short_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 pamd_th:\t%d\n", cfg->rx_cfg.pamd_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 mr_th:\t%d\n", cfg->rx_cfg.mr_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 atdc_th:\t%d\n", cfg->rx_cfg.atdc_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 prx_th:\t%d\n", cfg->rx_cfg.prx_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 atdev_th:\t%d\n", cfg->rx_cfg.atdev_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 smg_th:\t%d\n", cfg->rx_cfg.smg_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis); + WCN_DBG(FM_NTC | MAIN, "MT6620 osc_freq:\t%d\n", cfg->rx_cfg.osc_freq); + + WCN_DBG(FM_NTC | MAIN, "MT6620 scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low); + WCN_DBG(FM_NTC | MAIN, "MT6620 scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high); + WCN_DBG(FM_NTC | MAIN, "MT6620 power_level:\t%d\n", cfg->tx_cfg.power_level); +#if 0 + WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_l:\t0x%04x\n", cfg->rx_cfg.long_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_s:\t0x%04x\n", cfg->rx_cfg.short_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 mr_th:\t0x%04x\n", cfg->rx_cfg.mr_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 cqi_th:\t0x%04x\n", cfg->rx_cfg.cqi_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 smg_th:\t0x%04x\n", cfg->rx_cfg.smg_th); + WCN_DBG(FM_NTC | MAIN, "MT6620 scan_ch_size:\t%d\n", cfg->rx_cfg.scan_ch_size); + WCN_DBG(FM_NTC | MAIN, "MT6620 seek_space:\t%d\n", cfg->rx_cfg.seek_space); + WCN_DBG(FM_NTC | MAIN, "MT6620 band:\t%d\n", cfg->rx_cfg.band); + WCN_DBG(FM_NTC | MAIN, "MT6620 band_freq_l:\t%d\n", cfg->rx_cfg.band_freq_l); + WCN_DBG(FM_NTC | MAIN, "MT6620 band_freq_h:\t%d\n", cfg->rx_cfg.band_freq_h); + WCN_DBG(FM_NTC | MAIN, "MT6620 scan_sort:\t%d\n", cfg->rx_cfg.scan_sort); + WCN_DBG(FM_NTC | MAIN, "MT6620 fake_ch_num:\t%d\n", cfg->rx_cfg.fake_ch_num); + WCN_DBG(FM_NTC | MAIN, "MT6620 fake_ch_rssi_th:\t%d\n", cfg->rx_cfg.fake_ch_rssi_th); + + for (i = 0; i < cfg->rx_cfg.fake_ch_num; i++) { + WCN_DBG(FM_NTC | MAIN, "fake_ch:\t%d\n", cfg->rx_cfg.fake_ch[i]); + } + + WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis); + WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq); + WCN_DBG(FM_NTC | MAIN, "scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low); + WCN_DBG(FM_NTC | MAIN, "scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high); + WCN_DBG(FM_NTC | MAIN, "power_level:\t%d\n", cfg->tx_cfg.power_level); +#endif + return 0; +} + +static fm_s32 MT6620cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg; + struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg; + + if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_LONG_MT6620", &rx_cfg->long_ana_rssi_th))) + {//FMR_RSSI_TH_L = 0x0301 + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_SHORT_MT6620", &rx_cfg->short_ana_rssi_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DESENSE_RSSI_MT6620", &rx_cfg->desene_rssi_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PAMD_TH_MT6620", &rx_cfg->pamd_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_MR_TH_MT6620", &rx_cfg->mr_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDC_TH_MT6620", &rx_cfg->atdc_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PRX_TH_MT6620", &rx_cfg->prx_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_SMG_TH_MT6620", &rx_cfg->smg_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DEEMPHASIS_MT6620", &rx_cfg->deemphasis))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_OSC_FREQ_MT6620", &rx_cfg->osc_freq))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_L_MT6620", &tx_cfg->scan_hole_low))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_H_MT6620", &tx_cfg->scan_hole_high))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FMT_PWR_LVL_MAX_MT6620", &tx_cfg->power_level))) + { + return ret; + } + else + { + WCN_DBG(FM_WAR | MAIN, "invalid key\n"); + return -1; + } +/* if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_L_MT6620", &rx_cfg->long_ana_rssi_th))) {//FMR_RSSI_TH_L = 0x0301 + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_S_MT6620", &rx_cfg->short_ana_rssi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_CQI_TH_MT6620", &rx_cfg->cqi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_MR_TH_MT6620", &rx_cfg->mr_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SMG_TH_MT6620", &rx_cfg->smg_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_CH_SIZE_MT6620", &rx_cfg->scan_ch_size))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_SORT_MT6620", &rx_cfg->scan_sort))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SEEK_SPACE_MT6620", &rx_cfg->seek_space))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_MT6620", &rx_cfg->band))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_L_MT6620", &rx_cfg->band_freq_l))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_H_MT6620", &rx_cfg->band_freq_h))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_MT6620", &rx_cfg->fake_ch[fm_index]))) { + fm_index += 1; + rx_cfg->fake_ch_num = (rx_cfg->fake_ch_num < fm_index) ? fm_index : rx_cfg->fake_ch_num; + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_RSSI_MT6620", &rx_cfg->fake_ch_rssi_th))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_DEEMPHASIS_MT6620", &rx_cfg->deemphasis))) { + return ret; + } else if (0 <= (ret = cfg_item_match(key, val, "FMR_OSC_FREQ_MT6620", &rx_cfg->osc_freq))) { + return ret; + } */ +} +static fm_s32 MT6620fm_cust_config_default(fm_cust_cfg *cfg) +{ + FMR_ASSERT(cfg); + + cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG_MT6620; + cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT_MT6620; + cfg->rx_cfg.desene_rssi_th = FM_RX_DESENSE_RSSI_MT6620; + cfg->rx_cfg.pamd_th = FM_RX_PAMD_TH_MT6620; + cfg->rx_cfg.mr_th = FM_RX_MR_TH_MT6620; + cfg->rx_cfg.atdc_th = FM_RX_ATDC_TH_MT6620; + cfg->rx_cfg.prx_th = FM_RX_PRX_TH_MT6620; + cfg->rx_cfg.smg_th = FM_RX_SMG_TH_MT6620; + cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS_MT6620; + cfg->rx_cfg.osc_freq = FM_RX_OSC_FREQ_MT6620; + + cfg->tx_cfg.scan_hole_low = FM_TX_SCAN_HOLE_LOW_MT6620; + cfg->tx_cfg.scan_hole_high = FM_TX_SCAN_HOLE_HIGH_MT6620; + cfg->tx_cfg.power_level = FM_TX_PWR_LEVEL_MAX_MT6620; + + return 0; +} + +static fm_s32 MT6620fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + fm_s8 *buf = NULL; + fm_s32 file_len = 0; + + if (!(buf = fm_zalloc(4096))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + return -ENOMEM; + } + +// fm_index = 0; + + file_len = fm_file_read(filename, buf, 4096, 0); + + if (file_len <= 0) { + ret = -1; + goto out; + } + + ret = cfg_parser(buf, MT6620cfg_item_handler, cfg); + +out: + + if (buf) { + fm_free(buf); + } + + return ret; +} +#define MT6620_FM_CUST_CFG_PATH "etc/fmr/mt6620_fm_cust.cfg" +fm_s32 MT6620fm_cust_config_setup(const fm_s8 *filepath) +{ + fm_s32 ret = 0; + fm_s8 *filep = NULL; + fm_s8 file_path[51] = {0}; + + MT6620fm_cust_config_default(&mt6620_fm_config); + WCN_DBG(FM_NTC | MAIN, "MT6620 FM default config\n"); + MT6620fm_cust_config_print(&mt6620_fm_config); + + if (!filepath) { + filep = MT6620_FM_CUST_CFG_PATH; + } else { + memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath)); + filep = file_path; + trim_path(&filep); + } + + ret = MT6620fm_cust_config_file(filep, &mt6620_fm_config); + WCN_DBG(FM_NTC | MAIN, "MT6620 FM cust config\n"); + MT6620fm_cust_config_print(&mt6620_fm_config); + + return ret; +} + +fm_u16 MT6620fm_cust_config_fetch(enum fm_cust_cfg_op op_code) +{ +#if 0 + fm_u16 tmp = 0; + fm_s32 i; + static fm_s32 fake_ch_idx = 0; + + switch (op_code) { + //For FM RX + case FM_CFG_RX_RSSI_TH_LONG: { + tmp = mt6620_fm_config.rx_cfg.long_ana_rssi_th; + break; + } + case FM_CFG_RX_RSSI_TH_SHORT: { + tmp = mt6620_fm_config.rx_cfg.short_ana_rssi_th; + break; + } + case FM_CFG_RX_CQI_TH: { + tmp = mt6620_fm_config.rx_cfg.cqi_th; + break; + } + case FM_CFG_RX_MR_TH: { + tmp = mt6620_fm_config.rx_cfg.mr_th; + break; + } + case FM_CFG_RX_SMG_TH: { + tmp = mt6620_fm_config.rx_cfg.smg_th; + break; + } + case FM_CFG_RX_SCAN_CH_SIZE: { + tmp = mt6620_fm_config.rx_cfg.scan_ch_size; + break; + } + case FM_CFG_RX_SEEK_SPACE: { + tmp = mt6620_fm_config.rx_cfg.seek_space; + break; + } + case FM_CFG_RX_BAND: { + tmp = mt6620_fm_config.rx_cfg.band; + break; + } + case FM_CFG_RX_BAND_FREQ_L: { + tmp = mt6620_fm_config.rx_cfg.band_freq_l; + break; + } + case FM_CFG_RX_BAND_FREQ_H: { + tmp = mt6620_fm_config.rx_cfg.band_freq_h; + break; + } + case FM_CFG_RX_SCAN_SORT: { + tmp = mt6620_fm_config.rx_cfg.scan_sort; + break; + } + case FM_CFG_RX_FAKE_CH_NUM: { + tmp = mt6620_fm_config.rx_cfg.fake_ch_num; + break; + } + case FM_CFG_RX_FAKE_CH: { + tmp = mt6620_fm_config.rx_cfg.fake_ch[fake_ch_idx]; + i = (mt6620_fm_config.rx_cfg.fake_ch_num > 0) ? mt6620_fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX; + fake_ch_idx++; + fake_ch_idx = fake_ch_idx % i; + break; + } + case FM_CFG_RX_FAKE_CH_RSSI: { + tmp = mt6620_fm_config.rx_cfg.fake_ch_rssi_th; + break; + } + case FM_CFG_RX_DEEMPHASIS: { + tmp = mt6620_fm_config.rx_cfg.deemphasis; + break; + } + case FM_CFG_RX_OSC_FREQ: { + tmp = mt6620_fm_config.rx_cfg.osc_freq; + break; + } + //For FM TX + case FM_CFG_TX_SCAN_HOLE_LOW: { + tmp = mt6620_fm_config.tx_cfg.scan_hole_low; + break; + } + case FM_CFG_TX_SCAN_HOLE_HIGH: { + tmp = mt6620_fm_config.tx_cfg.scan_hole_high; + break; + } + case FM_CFG_TX_PWR_LEVEL: { + tmp = mt6620_fm_config.tx_cfg.power_level; + break; + } + default: + break; + } + + WCN_DBG(FM_DBG | MAIN, "mt6620_cust cfg %d: 0x%04x\n", op_code, tmp); + return tmp; +#endif + return 0; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c new file mode 100755 index 000000000000..4ab2d358e2a1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c @@ -0,0 +1,55 @@ +/* mt6620_fm_eint.c + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6620 FM Radio Driver -- EINT functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #if 0 +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_eint.h" + +fm_s32 fm_enable_eint(void) +{ + return 0; +} + +fm_s32 fm_disable_eint(void) +{ + return 0; +} + +fm_s32 fm_request_eint(void (*parser)(void)) +{ + WCN_DBG(FM_NTC|EINT,"%s\n", __func__); + + mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser); + + return 0; +} + +fm_s32 fm_eint_pin_cfg(fm_s32 mode) +{ + return 0; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c new file mode 100755 index 000000000000..cb8ff82c3543 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c @@ -0,0 +1,2212 @@ +#include +#include +#include + +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_utils.h" +#include "fm_patch.h" +#include "fm_link.h" +#include "fm_config.h" +#include "fm_private.h" + +#include "mt6620_fm_reg.h" +#include "mt6620_fm.h" +//#include "mt6620_drv_dsp.h" +//#include "mt6620_fm_link.h" +#include "mt6620_fm_lib.h" +#include "mt6620_fm_cmd.h" +#include "mt6620_fm_cust_cfg.h" +#ifdef MTK_FM_50KHZ_SUPPORT +static struct fm_fifo *cqi_fifo = NULL; +#endif +extern fm_cust_cfg mt6620_fm_config; +static struct fm_hw_info mt6620_hw_info = { + .chip_id = 0x00006620, + .eco_ver = 0x00000000, + .rom_ver = 0x00000002, + .patch_ver = 0x00000111, + .reserve = 0x00000000, +}; +static struct fm_i2s_info mt6620_i2s_inf = { + .status = 0, //i2s off + .mode = 0, //slave mode + .rate = 48000, //48000 sample rate +}; + +fm_s32 MT6620_HL_Side_Adj(fm_u16 freq, fm_s32 *hl); +fm_s32 MT6620_ADPLL_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid); +fm_s32 MT6620_MCU_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid); +fm_s32 MT6620_ADPLL_Power_OnOff(fm_s32 onoff, fm_s32 ADPLL_clk); +fm_s32 MT6620_TX_PWR_CTRL(fm_u16 freq, fm_s32 *ctr); +fm_s32 MT6620_RTC_Drift_CTRL(fm_u16 freq, fm_s32 *ctr); +fm_s32 MT6620_TX_DESENSE(fm_u16 freq, fm_s32 *ctr); + +static fm_s32 mt6620_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample); +static fm_s32 mt6620_desense_check(fm_u16 freq,fm_s32 rssi); +static fm_s32 MT6620_Rds_Tx(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt); +static fm_s32 MT6620_Rds_Tx_Enable(void); +static fm_s32 MT6620_Rds_Tx_Disable(void); + +static fm_u8 *cmd_buf = NULL; +static struct fm_lock *cmd_buf_lock = NULL; +static struct fm_callback *fm_cb_op; +//static struct MT6620fm_priv priv_adv_6620; +static ENUM_WMTHWVER_TYPE_T hw_ver=WMTHWVER_MT6620_E3; +static fm_s32 mt6620_pwron(fm_s32 data) +{ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM)) { + WCN_DBG(FM_ALT | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } else { + /* GeorgeKuo: turn on function before check stp ready */ + if(fm_false == mtk_wcn_stp_is_ready()) + { + WCN_DBG(FM_ALT | MAIN,"6620 stp is not ready, please retry later\n"); + return -FM_ELINK; + } + hw_ver = mtk_wcn_wmt_hwver_get(); + WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n"); + return 0; + } +} + + +static fm_s32 mt6620_pwroff(fm_s32 data) +{ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM)) { + WCN_DBG(FM_ALT | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } else { + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; + } +} + +static fm_s32 Delayms(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data); + msleep(data); + return 0; +} + +static fm_s32 Delayus(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data); + udelay(data); + return 0; +} + +static struct fm_res_ctx *res = NULL; + +fm_s32 mt6620_get_read_result(struct fm_res_ctx* result) +{ + FMR_ASSERT(result); + res = result; + + return 0; +} + +static fm_s32 mt6620_read(fm_u8 addr, fm_u16 *val) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_get_reg(cmd_buf, TX_BUF_SIZE, addr); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_RD, SW_RETRY_CNT, FSPI_RD_TIMEOUT, mt6620_get_read_result); + + if (!ret && res) { + *val = res->fspi_rd; + } + + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +static fm_s32 mt6620_write(fm_u8 addr, fm_u16 val) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_set_reg(cmd_buf, TX_BUF_SIZE, addr, val); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_WR, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +static fm_s32 mt6620_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask) +{ + fm_s32 ret = 0; + fm_u16 val; + + ret = mt6620_read(addr, &val); + + if (ret) + return ret; + + val = ((val & (mask)) | bits); + ret = mt6620_write(addr, val); + + return ret; +} + +static fm_u16 mt6620_get_chipid(void) +{ + return 0x6620; +} + +/* mt6620_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static fm_s32 mt6620_SetAntennaType(fm_s32 type) +{ + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + + if (type == FM_ANA_LONG) { + //Long Antenna RSSI threshold, 0xE0 D0~D9 + mt6620_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG_MT6620 & 0x03FF))); + //Turn on Short Antenna LNA and Off TR Switch + mt6620_write(0x04, 0x0142); + //Turn off the Short Antenna Capbank biasing + mt6620_write(0x05, 0x00E7); + //Turn off the Short Antenna Capbank biasing + mt6620_write(0x26, 0x0004); + //Disable concurrent calibration for VCO and SCAL + mt6620_write(0x2E, 0x0008); + } else if (type == FM_ANA_SHORT) { + //Short Antenna RSSI threshold, 0xE0 D0~D9 + mt6620_write(0xE0, ((0xA2E0 & 0xFC00) | (FMR_RSSI_TH_SHORT_MT6620 & 0x03FF))); + //Turn on Short Antenna LNA and TR Switch + mt6620_write(0x04, 0x0145); + //Turn on the Short Antenna Capbank biasing + mt6620_write(0x05, 0x00FF); + //Turn on the Short Antenna Capbank biasing + mt6620_write(0x26, 0x0024); + //Enable concurrent calibration for VCO and SCAL + mt6620_write(0x2E, 0x0000); + } else { + WCN_DBG(FM_ERR | CHIP, "%s()\n", __func__); + return -FM_EPARA; + } + + return 0; +} + +static fm_s32 mt6620_GetAntennaType(void) +{ + fm_u16 dataRead; + + mt6620_read(0x2E, &dataRead); + + if (dataRead == 0x0000) + return FM_ANA_SHORT; //short antenna + else + return FM_ANA_LONG; //long antenna +} + +static fm_s32 mt6620_Mute(fm_bool mute) +{ + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + + if (mute) { + return mt6620_set_bits(0x9C, 0x0008, 0xFFF7); //1:9C D3 = 1 + } else { + return mt6620_set_bits(0x9c, 0x0000, 0xFFF7); //1:9C D3 = 0 + } +} + +static fm_s32 mt6620_RampDown(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + WCN_DBG(FM_NTC | CHIP, "ramp down\n"); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_rampdown(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down failed\n"); + } + + return ret; +} +#if 0//ramp down tx will do in tx tune flow +static fm_s32 MT6620_RampDown_Tx(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size = 0; + + WCN_DBG(FM_NTC | CHIP, "ramp down TX\n"); + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + + pkt_size = mt6620_rampdown_tx(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size,FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT,NULL); + + FM_UNLOCK(cmd_buf_lock); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down TX failed\n"); + } + return ret; +} +#endif +static fm_s32 mt6620_PowerUp(fm_u16 *chip_id, fm_u16 *device_id) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + FMR_ASSERT(chip_id); + FMR_ASSERT(device_id); + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + //Wholechip FM Power Up: step 1, mt6620_off_2_longANA + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_off_2_longANA_1(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_longANA_1 failed\n"); + return ret; + } + + Delayms(100); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_off_2_longANA_2(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_longANA_2 failed\n"); + return ret; + } + + Delayms(50); + + // *chip_id = 0x6620; + // *device_id = 0x6620; + // WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", 0x6620); + + //Wholechip FM Power Up: step 2, FM Digital Init: fm_rgf_maincon + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_pwrup_digital_init_1(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_2 failed\n"); + return ret;; + } + + Delayms(10); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_pwrup_digital_init_2(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_2 failed\n"); + return ret;; + } + + Delayms(10); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_pwrup_digital_init_3(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_3 failed\n"); + return ret;; + } +#ifdef FM_DIGITAL_INPUT + #ifdef MT6573 //for MT6573 + if(get_chip_eco_ver() == CHIP_E1){ + ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_MASTER, MT6620_I2S_48K); + }else{ + ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K); + } + #else + ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K); + #endif + if(ret){ + WCN_DBG(FM_ERR |CHIP,"pwron set I2S on error\n"); + return ret; + } + //we will disable 6620 fm chip analog output when use I2S path, set 0x3A bit2 = 0 + //mt6620_set_bits(0x3A, 0, MASK(2)); + WCN_DBG(FM_NTC |CHIP,"pwron set I2S on ok\n"); +#endif + + mt6620_hw_info.eco_ver = (fm_s32)mtk_wcn_wmt_hwver_get(); + WCN_DBG(FM_DBG | CHIP, "pwr on seq ok\n"); + return ret; +} +static fm_s32 mt6620_PowerUpTx(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "pwr on Tx seq......\n"); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_off_2_tx_shortANA(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_tx_shortANA failed\n"); + return ret; + } + + + mt6620_read(0x62, &dataRead); + WCN_DBG(FM_NTC | CHIP, "Tx on chipid=%x\n",dataRead); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_dig_init(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_dig_init failed\n"); + return ret; + } + //get temprature + if(mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE) != fm_true) + { + WCN_DBG(FM_ERR | MAIN, "wmt_therm_ctrl, WMTTHERM_ENABLE failed\n"); + ret = -FM_ELINK; + return ret; + } +#ifdef FM_DIGITAL_INPUT + ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K); + if(ret){ + WCN_DBG(FM_ERR |CHIP,"pwron tx set I2S on error\n"); + return ret; + } + //we will disable 6620 fm chip analog output when use I2S path, set 0x3A bit2 = 0 + //mt6620_set_bits(0x3A, 0, MASK(2)); + WCN_DBG(FM_NTC |CHIP,"pwron set I2S on ok\n"); +#endif + + WCN_DBG(FM_DBG | CHIP, "pwr on tx seq ok\n"); + return ret; +} + +static fm_s32 mt6620_PowerDown(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + + // mt6620_RampDown(); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_pwrdown(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_pwrdown failed\n"); + return ret; + } + + return ret; +} + +static fm_s32 mt6620_PowerDownTx(void) +{ + fm_s32 ret = 0; + + if(mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE) != fm_true) + { + WCN_DBG(FM_ERR | MAIN, "wmt_therm_ctrl, WMTTHERM_DISABLE failed\n"); + ret = -FM_ELINK; + } + + return ret; +} + +static fm_bool MT6620_SetFreq_Tx(fm_u16 freq) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + fm_cb_op->cur_freq_set(freq); + //start tune + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_tune_tx(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_tune_tx failed\n"); + return ret;; + } + + Delayms(125); + + WCN_DBG(FM_DBG | CHIP, "mt6620_tune_tx to %d ok\n", freq); + + return fm_true; +} + +/* + * fm_print_curCQI -- print cur freq's CQI + * @cur_freq, current frequency + * If OK, return 0, else error code + */ +static fm_s32 mt6620_print_curCQI(fm_u16 cur_freq) +{ + fm_s32 ret = 0; + fm_u16 rssi = 0; + fm_u16 pamd = 0; + fm_u16 mr = 0; + + if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG0))) + return ret; + if((ret = mt6620_read(FM_RSSI_IND, &rssi))) + return ret; + if((ret = mt6620_read(FM_ADDR_PAMD, &pamd))) + return ret; + if((ret = mt6620_read(FM_MR_IND, &mr))) + return ret; + + WCN_DBG(FM_NTC |CHIP,"FREQ=%d, RSSI=0x%04x, PAMD=0x%04x, MR=0x%04x\n", (fm_s32)cur_freq, rssi, pamd, mr); + return ret; +} + +static fm_bool mt6620_SetFreq(fm_u16 freq) +{ + fm_s32 ret = 0; + fm_s32 hl_side = -1; + fm_s32 freq_avoid = -1; + fm_u16 pkt_size; + + fm_cb_op->cur_freq_set(freq); + + if((ret = MT6620_HL_Side_Adj(freq, &hl_side))) + return ret; + WCN_DBG(FM_NTC |CHIP,"%s, [hl_side=%d]\n", __func__, hl_side); + + if((ret = MT6620_ADPLL_Freq_Avoid(freq, &freq_avoid))) + return ret; + WCN_DBG(FM_NTC |CHIP,"%s, adpll [freq_avoid=%d]\n", __func__, freq_avoid); + +// hw_ver = mtk_wcn_wmt_hwver_get(); + if(hw_ver >= WMTHWVER_MT6620_E3) + { + if((ret = MT6620_MCU_Freq_Avoid(freq, &freq_avoid))) + return ret; + WCN_DBG(FM_NTC |CHIP,"%s, mcu [freq_avoid=%d]\n", __func__, freq_avoid); + } + else + { + WCN_DBG(FM_NTC |CHIP,"%s, no need do mcu freq avoid[hw_ver=%d]\n", __func__, hw_ver); + } + + //start tune + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_tune_1(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_tune_1 failed\n"); + return ret;; + } + + Delayms(200); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_tune_2(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_tune_2 failed\n"); + return ret;; + } + + Delayms(35); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_tune_3(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_tune_3 failed\n"); + return ret;; + } + + ret = mt6620_print_curCQI(freq); + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + + return fm_true; +} + + +static fm_s32 mt6620_TxScan_SetFreq(fm_u16 freq) +{ + fm_s32 ret = 0; + fm_u16 pkt_size = 0; + + WCN_DBG(FM_NTC | CHIP,"+%s():[freq=%d]\n", __func__, freq); + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + + pkt_size = mt6620_tune_txscan(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + FM_UNLOCK(cmd_buf_lock); + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +} + +static fm_s32 mt6620_TxScan_GetCQI(fm_s16 *pRSSI, fm_s16 *pPAMD, fm_s16 *pMR) +{ + fm_s32 cnt = 0; + fm_s32 ret = 0; + fm_s16 tmp_reg = 0; + fm_s16 aRSSI = 0; + fm_s16 aPAMD = 0; + fm_s16 aMR = 0; + + WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__); + + if((pRSSI == NULL) || (pPAMD == NULL) || (pMR == NULL)){ + WCN_DBG(FM_ERR | CHIP,"%s():para error, [pRSSI=%p],[aPAMD=%p],[pMR=%p]\n", + __func__, pRSSI, pPAMD, pMR); + ret = -FM_EPARA; + goto out; + } + + for(cnt = 0; cnt < 8; cnt++) + { + Delayms(3); + if((ret = mt6620_read(FM_RSSI_IND, &tmp_reg))) + goto out; + tmp_reg = tmp_reg&0x03ff; + tmp_reg = (tmp_reg > 511) ? ((fm_s16)(tmp_reg-1024)) : tmp_reg; + aRSSI += tmp_reg; + + if((ret = mt6620_read(FM_ADDR_PAMD, &tmp_reg))) + goto out; + tmp_reg = tmp_reg&0x00ff; + tmp_reg = (tmp_reg > 127) ? ((fm_s16)(tmp_reg-256)) : tmp_reg; + aPAMD += tmp_reg; + + if((ret = mt6620_read(FM_MR_IND, &tmp_reg))) + goto out; + tmp_reg = tmp_reg&0x01ff; + tmp_reg = (tmp_reg > 255) ? ((fm_s16)(tmp_reg-512)) : tmp_reg; + aMR += tmp_reg; + } + + *pRSSI = aRSSI>>3; + *pPAMD = aPAMD>>3; + *pMR = aMR>>3; + + WCN_DBG(FM_NTC | CHIP,"%s():[RSSI=%d],[PAMD=%d],[MR=%d]\n", + __func__, *pRSSI, *pPAMD, *pMR); + +out: + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +} + +static fm_s32 mt6620_TxScan_IsEmptyChannel(fm_s16 RSSI, fm_s16 PAMD, fm_s16 MR, fm_s32 *empty) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_NTC | CHIP,"+%s():[RSSI=%d],[PAMD=%d],[MR=%d]\n", __func__, RSSI, PAMD, MR); + + if(empty == NULL) + { + WCN_DBG(FM_NTC | CHIP,"invalid pointer [empty=0x%x]!\n", (fm_u32)empty); + ret = -FM_EPARA; + goto out; + } + + *empty = fm_true; + if(RSSI > FM_TXSCAN_RSSI_TH){ + *empty = fm_false; + goto out; + } + + if(PAMD < FM_TXSCAN_PAMD_TH){ + *empty = fm_false; + goto out; + } + + if(MR < FM_TXSCAN_MR_TH){ + *empty = fm_false; + goto out; + } + +out: + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +} + +static fm_s32 mt6620_TxScan(fm_u16 min_freq, + fm_u16 max_freq, + fm_u16 *pFreq, + fm_u16 *pScanTBL, + fm_u16 *ScanTBLsize, + fm_u16 scandir, + fm_u16 space) +{ + fm_s32 ret = 0; + fm_u16 freq = *pFreq; + fm_u16 scan_cnt = *ScanTBLsize; + fm_u16 cnt = 0; + fm_s16 rssi = 0; + fm_s16 pamd = 0; + fm_s16 mr = 0; + fm_s32 counter = 0; + fm_s32 empty = -1; + fm_s32 step; + + WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__); + + if((!pScanTBL) || (*ScanTBLsize < FM_TX_SCAN_MIN) || (*ScanTBLsize > FM_TX_SCAN_MAX)) + { + WCN_DBG(FM_ERR | CHIP,"+%s():invalid scan table\n", __func__); + ret = -FM_EPARA; + goto out; + } + + WCN_DBG(FM_NTC | CHIP, "[freq=%d], [max_freq=%d],[min_freq=%d],[scan BTL size=%d],[scandir=%d],[space=%d]\n", + *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space); + + cnt = 0; + /* if (space == MT6620_FM_SPACE_100K) { + step = 1; + } else if (space == MT6620_FM_SPACE_50K) { + step = 5; + } else if (space == MT6620_FM_SPACE_200K) { + step = 2; + } else { + //default + step = 1; + }*/ + step = space; + while(!(!(cnt < scan_cnt) || (freq > max_freq) || (freq < min_freq))){ + //MT6620_RampDown(); + //Set desired channel, tune to the channel, and perform fast AGC + counter++; //just for debug + + ret = mt6620_TxScan_SetFreq(freq); + if(ret){ + WCN_DBG(FM_ERR | CHIP,"%s():set freq failed\n", __func__); + goto out; + } + + //wait 8~10ms for RF setting + Delayms(10); + //wait 4 AAGC period for AAGC setting, AAGC period = 1024/480k = 2.13ms + Delayms(9); + + ret = mt6620_TxScan_GetCQI(&rssi, &pamd, &mr); + if(ret){ + WCN_DBG(FM_ERR | CHIP,"%s():get CQI failed\n", __func__); + goto out; + } + + ret = mt6620_TxScan_IsEmptyChannel(rssi, pamd, mr, &empty); + if(!ret){ + if((empty == fm_true) && ((freq < FM_TX_SCAN_HOLE_LOW) || (freq > FM_TX_SCAN_HOLE_HIGH))){ + *(pScanTBL + cnt) = freq; //strore the valid empty channel + cnt++; + WCN_DBG(FM_NTC | CHIP,"empty channel:[freq=%d] [cnt=%d]\n", freq, cnt); + } + }else{ + WCN_DBG(FM_ERR | CHIP,"%s():IsEmptyChannel failed\n", __func__); + goto out; + } + + if(scandir == FM_TX_SCAN_UP){ + if(freq == FM_TX_SCAN_HOLE_LOW){ + freq += (FM_TX_SCAN_HOLE_HIGH - FM_TX_SCAN_HOLE_LOW + step); + }else{ + freq += step; + } + }else if(scandir == FM_TX_SCAN_DOWN){ + if(freq == FM_TX_SCAN_HOLE_HIGH){ + freq -= (FM_TX_SCAN_HOLE_HIGH - FM_TX_SCAN_HOLE_LOW + step); + }else{ + freq -= step; + } + }else{ + WCN_DBG(FM_ERR | CHIP,"%s():scandir para error\n", __func__); + ret = -FM_EPARA; + goto out; + } + } + + *ScanTBLsize = cnt; + *pFreq = *(pScanTBL + cnt); + WCN_DBG(FM_NTC | CHIP, "completed, [cnt=%d],[freq=%d],[counter=%d]\n", cnt, freq, counter); + +out: + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +} + +/* +* mt6620_Seek +* @pFreq - IN/OUT parm, IN start freq/OUT seek valid freq +* @seekdir - 0:up, 1:down +* @space - 1:50KHz, 2:100KHz, 4:200KHz +* return fm_true:seek success; fm_false:seek failed +*/ +static fm_bool mt6620_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space) +{ + fm_s32 ret = 0; + fm_u16 pkt_size,temp; + + mt6620_RampDown(); + mt6620_read(0x9C, &temp); + mt6620_Mute(fm_true); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_seek_1(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + *pFreq = res->seek_result; + fm_cb_op->cur_freq_set(*pFreq); + } else { + WCN_DBG(FM_ALT | CHIP, "mt6620_seek_1 failed\n"); + return ret; + } + + Delayms(35); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_seek_2(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_seek_2 failed\n"); + return ret; + } + + //get the result freq + WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq); + if((temp&0x0008) == 0) + { + mt6620_Mute(fm_false); + } + + return fm_true; +} + +static fm_bool mt6620_Scan(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL, + fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space) +{ + fm_s32 ret = 0; + fm_u16 pkt_size,temp; + fm_u16 offset = 0; + fm_u16 tmp_scanTBLsize = *ScanTBLsize; + + if ((!pScanTBL) || (tmp_scanTBLsize == 0)) { + WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n"); + return fm_false; + } + + WCN_DBG(FM_DBG | CHIP, "start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space); + + mt6620_RampDown(); + mt6620_read(0x9C, &temp); + mt6620_Mute(fm_true); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_scan_1(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_SCAN_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE); + WCN_DBG(FM_INF | CHIP, "Rx Scan Result:\n"); + + for (offset = 0; offset < tmp_scanTBLsize; offset++) { + WCN_DBG(FM_INF | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset)); + } + + *ScanTBLsize = tmp_scanTBLsize; + } else { + WCN_DBG(FM_ALT | CHIP, "mt6620_scan_1 failed\n"); + return ret; + } + + Delayms(35); + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_scan_2(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_scan_2 failed\n"); + return ret; + } + + if((temp&0x0008) == 0) + { + mt6620_Mute(fm_false); + } + + return fm_true; +} + +/* + * mt6620_GetCurRSSI - get current freq's RSSI value + * RS=RSSI + * If RS>511, then RSSI(dBm)= (RS-1024)/16*6 + * else RSSI(dBm)= RS/16*6 + */ +static fm_s32 mt6620_GetCurRSSI(fm_s32 *pRSSI) +{ + fm_u16 tmp_reg; + + mt6620_read(FM_RSSI_IND, &tmp_reg); + tmp_reg = tmp_reg & 0x03ff; + + if (pRSSI) { + *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4); + WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI); + } else { + WCN_DBG(FM_ERR | CHIP, "get rssi para error\n"); + return -FM_EPARA; + } + + return 0; +} + +static fm_s32 MT6620_Fast_SetFreq(fm_u16 freq) +{ + fm_s32 ret = 0; + fm_u16 pkt_size = 0; + + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_fast_tune(cmd_buf, TX_BUF_SIZE, freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6620_fast_tune failed\n"); + return ret; + } + return ret; +} + +/* + * mt6620_get_RSSI - set freq and return RSSI value +* + */ +static fm_s32 mt6620_GetFreqCQI(fm_u16 freq,fm_s32 *pRSSI) +{ + if(MT6620_Fast_SetFreq(freq)) + { + mt6620_GetCurRSSI(pRSSI); + } + + return 0; +} + +static fm_u8 mt6620_vol_tbl[16] = { + 0, 1, 2, 3, 4, 5, 7, 9, 11, 14, 17, 21, 25, 30, 36, 43 +}; +static fm_s32 mt6620_SetVol(fm_u8 vol) +{ + fm_s32 ret = 0; + fm_u8 tmp_vol;// = vol & 0x3f; + + vol = (vol > 15) ? 15 : vol; + tmp_vol = mt6620_vol_tbl[vol] & 0x3f; + if (tmp_vol > MT6620_VOL_MAX) + tmp_vol = MT6620_VOL_MAX; + + ret = mt6620_set_bits(0x9C, (tmp_vol << 8), 0xC0FF); + + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", tmp_vol); + return ret; + } else { + WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", tmp_vol); + } + + return 0; +} + +static fm_s32 mt6620_GetVol(fm_u8 *pVol) +{ + fm_s32 ret = 0; + fm_u16 tmp_reg; + + FMR_ASSERT(pVol); + + ret = mt6620_read(0x9C, &tmp_reg); + + if (ret) { + *pVol = 0; + WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n"); + return ret; + } else { + *pVol = (tmp_reg >> 8) & 0x3f; + if(*pVol == MT6620_VOL_MAX) + *pVol = 15; + else + *pVol = (*pVol/3); + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + } + + return 0; + +} + +static fm_s32 mt6620_dump_reg(void) +{ + fm_s32 i; + fm_u16 TmpReg; + for(i=0; i<0xff; i++) + { + mt6620_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg); + } + return 0; +} + + +static fm_bool mt6620_GetMonoStereo(fm_u16 *pMonoStereo) +{ + fm_u16 tmp_reg; + + mt6620_write(FM_MAIN_PGSEL, 0x0001); + + if (pMonoStereo) { + mt6620_read(0xF8, &tmp_reg); + *pMonoStereo = (tmp_reg & 0x0400) >> 10; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return fm_false; + } + + mt6620_write(FM_MAIN_PGSEL, 0x0000); + + WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo); + return fm_true; +} + +/* + * MT6620_SetMonoStereo + * Force set to stero/mono mode + * @MonoStereo -- 0, auto; 1, force mono + * If success, return 0; else error code + */ +static fm_s32 MT6620_SetMonoStereo(fm_s32 MonoStereo) +{ + fm_u16 tmp_reg; + fm_s32 ret = 0; + + if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG1))) + goto out; + + tmp_reg = MonoStereo ? BITn(1) : 0; //MonoStereo, 1: force mono; 0:auto + if((ret = mt6620_set_bits(FM_STEROMONO_CTR, tmp_reg, MASK(1))))//set E0 D1=0 + goto out; + + if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG0))) + goto out; + + WCN_DBG(FM_DBG | CHIP,"set to %s\n", MonoStereo ? "auto" : "force mono"); + +out: + return ret; +} + +static fm_s32 mt6620_GetCapArray(fm_s32 *ca) +{ + fm_u16 dataRead; + + FMR_ASSERT(ca); + + mt6620_read(0x26, &dataRead); + *ca = dataRead; + + return 0; +} + +/* + * mt6620_GetCurPamd - get current freq's PAMD value + * PA=PAMD + * If PA>511 then PAMD(dB)= (PA-1024)/16*6, + * else PAMD(dB)=PA/16*6 + */ +static fm_bool mt6620_GetCurPamd(fm_u16 *pPamdLevl) +{ + fm_u16 tmp_reg; + fm_u16 dBvalue=0,valid_cnt=0; + fm_s32 i,total=0; + + for (i = 0; i < 8; i++) + { + if (mt6620_read(FM_ADDR_PAMD, &tmp_reg)) + { + *pPamdLevl = 0; + return fm_false; + } + + tmp_reg &= 0x00FF; + dBvalue = (tmp_reg>127) ? ((256-tmp_reg)*6/16):0; + if(dBvalue != 0) + { + total += dBvalue; + valid_cnt++; + WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue); + } + Delayms(3); + } + if(valid_cnt != 0) + { + *pPamdLevl = total/valid_cnt; + } + else + { + *pPamdLevl = 0; + } + WCN_DBG(FM_DBG | CHIP,"PamdLevl=%d\n", *pPamdLevl); + return fm_true; +} + +static fm_s32 mt6620_ScanStop(void) +{ + return fm_force_active_event(FLAG_SCAN); +} + +static fm_s32 mt6620_SeekStop(void) +{ + return fm_force_active_event(FLAG_SEEK); +} + +/* + * mt6620_I2s_Setting - set the I2S state on MT6620 + * @onoff - I2S on/off + * @mode - I2S mode: Master or Slave + * + * Return:0, if success; error code, if failed + */ +static fm_s32 mt6620_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample) +{ + fm_u16 tmp_state = 0; + fm_u16 tmp_mode = 0; + fm_u16 tmp_sample = 0; + fm_s32 ret = 0; + + if (onoff == MT6620_I2S_ON) { + tmp_state = 0x01; //I2S Frequency tracking on + mt6620_i2s_inf.status = 1; + } else if (onoff == MT6620_I2S_OFF) { + tmp_state = 0x00; //I2S Frequency tracking off + mt6620_i2s_inf.status = 0; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff); + ret = -FM_EPARA; + goto out; + } + + if (mode == MT6620_I2S_MASTER) { + tmp_mode = 0x03; //6620 as I2S master + mt6620_i2s_inf.mode = 1; + } else if (mode == MT6620_I2S_SLAVE) { + tmp_mode = 0x0B; //6620 as I2S slave + mt6620_i2s_inf.mode = 0; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode); + ret = -FM_EPARA; + goto out; + } + + if (sample == MT6620_I2S_32K) { + tmp_sample = 0x0000; //6620 I2S 32KHz sample rate + mt6620_i2s_inf.rate = 32000; + } else if (sample == MT6620_I2S_44K) { + tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate + mt6620_i2s_inf.rate = 44100; + } else if (sample == MT6620_I2S_48K) { + tmp_sample = 0x1000; //6620 I2S 48KHz sample rate + mt6620_i2s_inf.rate = 48000; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample); + ret = -FM_EPARA; + goto out; + } + + if ((ret = mt6620_set_bits(0x5F, tmp_sample, 0xE7FF))) + goto out; + + if ((ret = mt6620_write(0x9B, tmp_mode))) + goto out; + + if ((ret = mt6620_set_bits(0x56, tmp_state, 0xFF7F))) + goto out; + + WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n", + (onoff == MT6620_I2S_ON) ? "On" : "Off", + (mode == MT6620_I2S_MASTER) ? "Master" : "Slave", + sample); +out: + return ret; +} +static fm_s32 mt6620_Tx_Support(fm_s32 *sup) +{ + *sup=1; + return 0; +} + +static fm_s32 mt6620_rdsTx_Support(fm_s32 *sup) +{ + *sup=1; + return 0; +} + +static fm_s32 MT6620_FMOverBT(fm_bool enable) +{ + fm_s32 ret = 0; + static fm_u16 state = 0; + static fm_u16 mode = 0; + static fm_u16 sample = 0; + static fm_u16 inited = fm_false; + + WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__); + if(inited == fm_false) + { + // record priv val + if((ret = mt6620_read(0x56, &state))) + goto out; + if((ret = mt6620_read(0x9B, &mode))) + goto out; + if((ret = mt6620_read(0x5F, &sample))) + goto out; + inited = fm_true; + WCN_DBG(FM_NTC | CHIP,"init, record priv seetings\n"); + } + + if(enable == fm_true){ + //disable analog output when FM over BT + if((ret = mt6620_set_bits(0x3A, 0, MASK(2)))) + goto out; + //set FM over BT + if((ret = mt6620_write(0x56, 0x0001))) + goto out; + if((ret = mt6620_write(0x9B, 0x000b))) + goto out; + if((ret = mt6620_write(0x5F, 0x1175))) + goto out; + WCN_DBG(FM_NTC | CHIP,"set FM via BT controller\n"); + } + else if(enable == fm_false) + { + //enable analog output when FM normal mode + if((ret = mt6620_set_bits(0x3A, BITn(2), MASK(2)))) + goto out; + //recover to priv val + if((ret = mt6620_write(0x56, state))) + goto out; + if((ret = mt6620_write(0x9B, mode))) + goto out; + if((ret = mt6620_write(0x5F, sample))) + goto out; + WCN_DBG(FM_NTC | CHIP,"set FM via Host\n"); + } + else + { + WCN_DBG(FM_ERR | CHIP,"%s()\n", __func__); + ret = -FM_EPARA; + goto out; + } +out: + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +} + +/*fm soft mute tune function*/ +static fm_s32 mt6620_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid) +{ + fm_s32 ret=0; + fm_u16 pkt_size; + fm_s32 hilo_side = -1; + struct mt6620_fm_softmute_tune_cqi_t *p_cqi; + fm_s32 RSSI=0, PAMD=0,MR=0, ATDC=0; + fm_u32 PRX=0; + fm_u16 softmuteGainLvl=0; + + /*set hilo side first(f/w won't do this), need to check whether work if set before rampdown*/ + if((ret = MT6620_HL_Side_Adj(freq, &hilo_side))) + return ret; + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6620_full_cqi_req(cmd_buf, TX_BUF_SIZE, freq, 1, 1); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6620_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) + { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]); + p_cqi = (struct mt6620_fm_softmute_tune_cqi_t*)&res->cqi[2]; + // just for debug + WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + p_cqi->ch, + p_cqi->rssi, + p_cqi->pamd, + p_cqi->mr, + p_cqi->atdc, + p_cqi->prx, + p_cqi->smg); + RSSI = ((p_cqi->rssi & 0x03FF) >= 512) ? ((p_cqi->rssi & 0x03FF) - 1024) : (p_cqi->rssi & 0x03FF); + PAMD = ((p_cqi->pamd & 0xFF) >= 128) ? ((p_cqi->pamd & 0x0FF) - 256) : (p_cqi->pamd & 0x0FF); + MR = ((p_cqi->mr & 0x01FF) >= 256) ? ((p_cqi->mr & 0x01FF) - 512) : (p_cqi->mr & 0x01FF); + ATDC =((p_cqi->atdc & 0x0FFF) >= 2048) ? ((p_cqi->atdc & 0x0FFF) - 4096) : (p_cqi->atdc & 0x0FFF); + if(ATDC < 0) + { + ATDC = (~(ATDC)) - 1;//Get abs value of ATDC + } + PRX = (p_cqi->prx & 0x00FF); + softmuteGainLvl = p_cqi->smg; + //check if the channel is valid according to each CQIs + if((RSSI >= mt6620_fm_config.rx_cfg.long_ana_rssi_th) + && (PAMD <= mt6620_fm_config.rx_cfg.pamd_th) + && (ATDC <= mt6620_fm_config.rx_cfg.atdc_th) + && (MR >= mt6620_fm_config.rx_cfg.mr_th) + && (PRX >= mt6620_fm_config.rx_cfg.prx_th) + && (softmuteGainLvl <= mt6620_fm_config.rx_cfg.smg_th)) + { + *valid = fm_true; + } + else + { + *valid = fm_false; + } + *rssi = RSSI; + } + else + { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return fm_false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid); + return fm_true; +} +static fm_s32 mt6620_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample) +{ + FMR_ASSERT(ponoff); + FMR_ASSERT(pmode); + FMR_ASSERT(psample); + + *ponoff = mt6620_i2s_inf.status; + *pmode = mt6620_i2s_inf.mode; + *psample = mt6620_i2s_inf.rate; + + return 0; +} + +static fm_s32 mt6620_hw_info_get(struct fm_hw_info *req) +{ + FMR_ASSERT(req); + + req->chip_id = mt6620_hw_info.chip_id; + req->eco_ver = mt6620_hw_info.eco_ver; + req->patch_ver = mt6620_hw_info.patch_ver; + req->rom_ver = mt6620_hw_info.rom_ver; + + return 0; +} + +static fm_bool mt6620_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value) +{ + fm_s32 ret = 0; + + WCN_DBG(FM_NTC | CHIP,"+%s():[group_idx=%d],[item_idx=%d],[item_value=%d]\n", + __func__, group_idx, item_idx, item_value); + + switch (group_idx){ + case mono: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + + if(item_value == 1){ + if((ret = mt6620_set_bits(0xE0, 0x02, 0xFFFF))) + goto out; + }else{ + if((ret = mt6620_set_bits(0xE0, 0x0, 0xFFFD))) + goto out; + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + case stereo: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if(item_value == 0){ + if((ret = mt6620_set_bits(0xE0, 0x0, 0xFFFD))) + goto out; + }else{ + switch (item_idx){ + case Sblend_ON: + if((ret = mt6620_set_bits(0xD8, item_idx<<15, 0x7FFF))) + goto out; + break; + case Sblend_OFF: + if((ret = mt6620_set_bits(0xD8, 0, 0x7FFF))) + goto out; + break; + } + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + case RSSI_threshold: + if((ret = mt6620_set_bits(0xe0, item_value, 0xFC00))) + goto out; + break; + case HCC_Enable: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if(item_idx){ + if((ret = mt6620_set_bits(0xCF, 0x10, 0xFFFF))) + goto out; + }else{ + if((ret = mt6620_set_bits(0xCF, 0x0, 0xFFEF))) + goto out; + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + case PAMD_threshold: + if((ret = mt6620_set_bits(0xE1, item_value, 0xFF00))) + goto out; + break; + case Softmute_Enable: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if(item_idx){ + if((ret = mt6620_set_bits(0xCF, 0x0020, 0xFFFF))) //1:CF[5] = 1 + goto out; + }else{ + if((ret = mt6620_set_bits(0xCF, 0x0000, 0xFFDF))) //1:CF[5] = 0 + goto out; + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + case De_emphasis: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if(item_idx == 2){ + if((ret = mt6620_set_bits(0xd4, 0x2000, 0xCFFF))) + goto out; + }else if(item_idx == 1){ + if((ret = mt6620_set_bits(0xd4, 0x1000, 0xCFFF))) + goto out; + }else if(item_idx == 0){ + if((ret = mt6620_set_bits(0xd4, 0x0000, 0xCFFF))) + goto out; + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + case HL_Side: + if(item_idx == 2){ + //H-Side + if((ret = mt6620_set_bits(0xCB, 0x11, 0xFFFE))) + goto out; + if((ret = mt6620_set_bits(0xF, 0x0400, 0xFBFF))) + goto out; + }else if(item_idx == 1){ + //L-Side + if((ret = mt6620_set_bits(0xCB, 0x10, 0xFFFE))) + goto out; + if((ret = mt6620_set_bits(0xF, 0x0, 0xFBFF))) + goto out; + } + break; + + case Dynamic_Limiter: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if(item_idx){ + if((ret = mt6620_set_bits(0xFA, 0x0, 0xFFF7))) + goto out; + }else{ + if((ret = mt6620_set_bits(0xFA, 0x08, 0xFFF7))) + goto out; + } + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + + case Softmute_Rate: + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01))) + goto out; + if((ret = mt6620_set_bits(0xc8, item_value<<8, 0x80FF))) + goto out; + if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0))) + goto out; + break; + + case AFC_Enable: + if (item_idx){ + if((ret = mt6620_set_bits(0x63, 0x0400, 0xFBFF))) + goto out; + }else{ + if((ret = mt6620_set_bits(0x63, 0x0, 0xFBFF))) + goto out; + } + break; + +#if 0 + case Softmute_Level: + mt6620_write(FM_MAIN_PGSEL, 0x01); + if(item_value > 0x24) + item_value = 0x24; + mt6620_set_bits(0xD1, item_value, 0xFFC0); + mt6620_write(FM_MAIN_PGSEL, 0x0); + break; +#endif + case Analog_Volume: + if((ret = mt6620_set_bits(0x9C, item_value<<8, 0xC0FF))) + goto out; + break; + + default: + break; + } + +out: + WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret); + return ret; +return fm_true; +} + +static const fm_u16 DesenseChMap[] = { + 0x0000, 0x0000, 0x0000, 0x0000, /* 7675~7600, 7755~7680, 7835~7760, 7915~7840 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 7995~7920, 8075~8000, 8155~8080, 8235~8160 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 8315~8240, 8395~8320, 8475~8400, 8555~8480 */ + 0x0000, 0x0000, 0x0000, 0x0400, /* 8635~8560, 8715~8640, 8795~8720, 8875~8800 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 8955~8880, 9035~8960, 9115~9040, 9195~9120 */ + 0x00FC, 0x0000, 0x0000, 0x1C00, /* 9275~9200, 9355~9280, 9435~9360, 9515~9440 */ + 0x0000, 0x0001, 0x0000, 0x0000, /* 9595~9520, 9675~9600, 9755~9680, 9835~9760 */ + 0x0000, 0x7800, 0x0000, 0x0000, /* 9915~9840, 9995~9920, 10075~10000, 10155~10080 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 10235~10160, 10315~10240, 10395~10320, 10475~10400 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 10555~10480, 10635~10560, 10715~10640, 10795~10720 */ + 0x0000 /* 10875~10800 */ +}; +// return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no +static fm_s32 mt6620_is_dese_chan(fm_u16 freq) +{ + fm_u8 bDesenseCh = 0; + + //caculate and applye compensation + if (0 == fm_get_channel_space(freq)) + { + freq *= 10; + } + WCN_DBG(FM_NTC | CHIP,"%s, freq=%d\n",__func__,freq); + + bDesenseCh = ((0x0001 << (((freq - 7600)%80)/5)) & DesenseChMap[((freq - 7600)/80)])>>(((freq - 7600)%80)/5); + WCN_DBG(FM_NTC | CHIP,"freq[%d] desense=[%d]\n",freq,bDesenseCh); + + return bDesenseCh; +} + +/* return value: +1, is desense channel and rssi is less than threshold; +0, not desense channel or it is but rssi is more than threshold.*/ +static fm_s32 mt6620_desense_check(fm_u16 freq,fm_s32 rssi) +{ + if(mt6620_is_dese_chan(freq)) + { + if(rssicb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb_op = &ops->cb; + + ops->bi.low_pwr_wa = MT6620fm_low_power_wa_default; + ops->bi.pwron = mt6620_pwron; + ops->bi.pwroff = mt6620_pwroff; + ops->bi.msdelay = Delayms; + ops->bi.usdelay = Delayus; + ops->bi.read = mt6620_read; + ops->bi.write = mt6620_write; + ops->bi.setbits = mt6620_set_bits; + ops->bi.chipid_get = mt6620_get_chipid; + ops->bi.mute = mt6620_Mute; + ops->bi.rampdown = mt6620_RampDown; + ops->bi.pwrupseq = mt6620_PowerUp; + ops->bi.pwrdownseq = mt6620_PowerDown; + ops->bi.setfreq = mt6620_SetFreq; + ops->bi.seek = mt6620_Seek; + ops->bi.seekstop = mt6620_SeekStop; + ops->bi.scan = mt6620_Scan; + ops->bi.scanstop = mt6620_ScanStop; + ops->bi.rssiget = mt6620_GetCurRSSI; + ops->bi.volset = mt6620_SetVol; + ops->bi.volget = mt6620_GetVol; + ops->bi.dumpreg = mt6620_dump_reg; + ops->bi.msget = mt6620_GetMonoStereo; + ops->bi.msset = MT6620_SetMonoStereo; + ops->bi.pamdget = mt6620_GetCurPamd; + ops->bi.em = mt6620_em_test; + ops->bi.anaswitch = mt6620_SetAntennaType; + ops->bi.anaget = mt6620_GetAntennaType; + ops->bi.caparray_get = mt6620_GetCapArray; + ops->bi.i2s_set = mt6620_I2s_Setting; + ops->bi.i2s_get = mt6620_i2s_info_get; + ops->bi.is_dese_chan = mt6620_is_dese_chan; + ops->bi.softmute_tune = mt6620_soft_mute_tune; + ops->bi.desense_check = mt6620_desense_check; + ops->bi.get_freq_cqi = mt6620_GetFreqCQI; + ops->bi.hwinfo_get = mt6620_hw_info_get; + ops->bi.fm_via_bt = MT6620_FMOverBT; + /*****tx function****/ + ops->bi.tx_support = mt6620_Tx_Support; + ops->bi.pwrupseq_tx = mt6620_PowerUpTx; + ops->bi.tune_tx = MT6620_SetFreq_Tx; + ops->bi.pwrdownseq_tx = mt6620_PowerDownTx; + ops->bi.tx_scan = mt6620_TxScan; + ops->ri.rds_tx = MT6620_Rds_Tx; + ops->ri.rds_tx_enable = MT6620_Rds_Tx_Enable; + ops->ri.rds_tx_disable = MT6620_Rds_Tx_Disable; + ops->ri.rdstx_support = mt6620_rdsTx_Support; + ops->bi.tx_pwr_ctrl = MT6620_TX_PWR_CTRL; + ops->bi.rtc_drift_ctrl = MT6620_RTC_Drift_CTRL; + ops->bi.tx_desense_wifi = MT6620_TX_DESENSE; + + cmd_buf_lock = fm_lock_create("20_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6620 fm lib alloc tx buf failed\n"); + ret = -1; + } + +#if 0//def MTK_FM_50KHZ_SUPPORT + cqi_fifo = fm_fifo_create("6620_cqi_fifo", sizeof(struct adapt_fm_cqi), 640); + if (!cqi_fifo) { + WCN_DBG(FM_ALT | CHIP, "6620 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +fm_s32 MT6620fm_low_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + //Basic functions. +#if 0//def MTK_FM_50KHZ_SUPPORT + fm_fifo_release(cqi_fifo); +#endif + + if (cmd_buf) { + fm_free(cmd_buf); + cmd_buf = NULL; + } + + ret = fm_lock_put(cmd_buf_lock); + + FMR_ASSERT(ops); + + fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface)); + return ret; +} + + +/*********************************************************************** +* Hi-Lo Side Injection +* +***********************************************************************/ +fm_s32 MT6620_HL_Side_Adj(fm_u16 freq, fm_s32 *hl) +{ + fm_s32 ret = 0; + fm_s32 isHiSide= 0; + fm_s32 tblsize = 0; + fm_s32 indx = 0; + fm_u16 tmp; + static fm_u16 Hi_Channels[] = {7950, 8070, 8210, 10640}; + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + *hl = 0; + + if(sizeof(Hi_Channels) == 0) + goto out; + + tblsize = sizeof(Hi_Channels)/sizeof(Hi_Channels[0]); + for(indx = 0; indx < tblsize; indx++){ + if(Hi_Channels[indx] == freq) + { + isHiSide = 1; + *hl = 1; + //goto set_HL; + break; + } + } + + if(isHiSide){ + //Set high-side injection (AFC) + if((ret = mt6620_read(0x0F, &tmp))) + goto out; + if((ret = mt6620_write(0x0F, tmp |0x0400))) + goto out; + if((ret = mt6620_write(FM_MAIN_PGSEL, 0))) + goto out; + //Set high-side injection (DFE) + if((ret = mt6620_read(0xCB, &tmp))) + goto out; + if((ret = mt6620_write(0xCB, tmp | 0x01))) + goto out; + //mt6620_write(0xCB, dataRead&0xFFFE); + }else{ + //Set low-side injection (AFC) + if((ret = mt6620_read(0x0F, &tmp))) + goto out; + if((ret = mt6620_write(0x0F, tmp&0xFBFF))) + goto out; + if((ret = mt6620_write(FM_MAIN_PGSEL, 0))) + goto out; + //Set low-side injection (DFE) + if((ret = mt6620_read(0xCB, &tmp))) + goto out; + //mt6620_write(0xCB, dataRead | 0x01); + if((ret = mt6620_write(0xCB, tmp&0xFFFE))) + goto out; + } + out: + WCN_DBG(FM_NTC | CHIP,"-%s, [isHiSide=%d][ret=%d]\n", __func__, (fm_s32)isHiSide, ret); + return ret; +} + +/*********************************************************************** +* ADPLL Power On or Off +* +***********************************************************************/ +fm_s32 MT6620_ADPLL_Power_OnOff(fm_s32 onoff, fm_s32 ADPLL_clk) +{ + fm_s32 ret = 0; + + + switch(onoff){ + case FM_ADPLL_ON: + if((ret = mt6620_write(0x25, 0x040F))) + goto out; + //Remove the Reset_N + if((ret = mt6620_write(0x20, 0x2720))) + goto out; + // change DLF loop gain + // Set FMCR_DLF_GAIN_A = "9" + // Set FMCR_DLF_GAIN_B = "9" + if((ret = mt6620_write(0x22, 0x9980))) + goto out; + //Configure initial I_CODE for calibration + if((ret = mt6620_write(0x25, 0x080F))) + goto out; + //Enable ADPLL DCO + //Set FMCR_DCO_ EN = "1 + if(ADPLL_clk == FM_ADPLL_16M){ + if((ret = mt6620_write(0x1E, 0x0A63))) + goto out; + // wait 5ms + Delayms(5); + if((ret = mt6620_write(0x1E, 0x0A65))) + goto out; + // wait 5ms + Delayms(5); + if((ret = mt6620_write(0x1E, 0x0A71))) + goto out; + }else if(ADPLL_clk == FM_ADPLL_15M){ + if((ret = mt6620_write(0x1E, 0x0863))) + goto out; + // wait 5ms + Delayms(5); + if((ret = mt6620_write(0x1E, 0x0865))) + goto out; + // wait 5ms + Delayms(5); + if((ret = mt6620_write(0x1E, 0x0871))) + goto out; + }else{ + ret = -FM_EPARA; + goto out; + } + // wait 100ms + Delayms(100); + if((ret = mt6620_write(0x2A, 0x1026))) + goto out; + break; + + //ADPLL Power Off Sequence + case FM_ADPLL_OFF: + // Set rgfrf_top_ck = "0" + if((ret = mt6620_set_bits(0x2A, 0, MASK(12))))//set 2A D12=0 + goto out; + // Set FMCR_OPEN_LOOP_EN = "0" + // Set FMCR_PLL_EN = "0" + // Set FMCR_DCO_EN = "0" + if((ret = mt6620_set_bits(0x1E, 0, MASK(7)&MASK(4)&MASK(0))))//set 1E D7 D4 D0=0 + goto out; + // Set rgfrf_adpll_reset_n = "0" + if((ret = mt6620_set_bits(0x20, 0, MASK(13))))//set 20 D13=0 + goto out; + // Set rgfrf_adpll_reset_n = "1" + if((ret = mt6620_set_bits(0x20, BITn(13), MASK(13))))//set 20 D13=1 + goto out; + break; + default: + break; + } +out: + return ret; +} + +/*********************************************************************** +* Frequency Avoidance +* +***********************************************************************/ +fm_s32 MT6620_ADPLL_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid) +{ + fm_s32 ret = 0; + fm_s32 ADPLL_clk = FM_ADPLL_15M; + fm_u16 dataRead = 0; + fm_u16 indx = 0; + static fm_u16 Avoid_Channels[] ={ + 7670, 7680, 7690, 7700, 8060, 8070, 8080, 8440, 8450, 8460, 8720, 8830, 8840, 9200, + 9210, 9220, 9230, 9360, 9490, 9600, 9610, 9980, 9990, 10000, 10130, 10360, 10370, 10380, 10740, + 10750, 10760, 10770 + }; + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + *freqavoid = 0; + + dataRead = sizeof(Avoid_Channels)/sizeof(Avoid_Channels[0]); + indx = 0; + while((indx < dataRead) && (ADPLL_clk != FM_ADPLL_16M)){ + if(Avoid_Channels[indx] == freq){ + ADPLL_clk = FM_ADPLL_16M; + *freqavoid = 1; + } + indx++; + } + //isADPLL_16M = 1; + if((ret = mt6620_read(0x1E, &dataRead))) + goto out; + if(((dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_16M))||(!(dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_15M)))//1EH, D9 + goto out; //we need not do freq avoid at these caes + + if(ADPLL_clk == FM_ADPLL_16M){ + //Set rgf_f16mode_en = X + if((ret = mt6620_set_bits(0x61, BITn(0), MASK(0))))//set 61H D0=1, 16.384MHZ + goto out; + }else if(ADPLL_clk == FM_ADPLL_15M){ + //Set rgf_f16mode_en = X + if((ret = mt6620_set_bits(0x61, 0, MASK(0))))//set 61H D0=0, 15.36MHZ + goto out; + }else{ + ret = -FM_EPARA; + goto out; + } + + // Disable ADPLL + ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_OFF, ADPLL_clk); + if(ret){ + WCN_DBG(FM_NTC | CHIP,"%s, ADPLL OFF failed, [ret=%d]n", __func__, ret); + goto out; + } + + //Set FMCR_DCO_CK_SEL = ? (default = 0, 15.36) + if(ADPLL_clk == FM_ADPLL_16M){ + if((ret = mt6620_set_bits(0x1E, BITn(9), MASK(9))))//set 1EH D9=1, 16.384MHZ + goto out; + }else if(ADPLL_clk == FM_ADPLL_15M){ + if((ret = mt6620_set_bits(0x1E, 0, MASK(9))))//set 1EH D9=0, 15.36MHZ + goto out; + }else{ + ret = -FM_EPARA; + goto out; + } + + // Ensable ADPLL + ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_ON, ADPLL_clk); + if(ret){ + WCN_DBG(FM_NTC | CHIP,"%s, ADPLL ON failed, [ret=%d]\n", __func__, ret); + goto out; + } + //Set rgfrf_cnt_resync_b = 0 + if((ret = mt6620_set_bits(0x2A, 0, MASK(1))))//set 2AH D1=0 + goto out; + //Set rgfrf_cnt_resync_b = 1 + if((ret = mt6620_set_bits(0x2A, BITn(1), MASK(1))))//set 2AH D1=1 + goto out; +out: + WCN_DBG(FM_NTC | CHIP,"-%s, [ADPLL_clk=%d][ret=%d]\n", __func__, (fm_s32)ADPLL_clk, ret); + return ret; +} + +/*********************************************************************** +* Frequency Avoidance +* +***********************************************************************/ +fm_s32 MT6620_MCU_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid) +{ + fm_s32 ret = 0; + fm_s32 mcuDsense = FM_MCU_DESE_DISABLE; + fm_u16 len = 0; + fm_u16 indx = 0; + static fm_u16 FreqList[] ={7800, 7940, 8320, 9260, 9600, 10400}; + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + *freqavoid = 0; + + len = sizeof(FreqList)/sizeof(FreqList[0]); + indx = 0; + while((indx < len) && (mcuDsense != FM_MCU_DESE_ENABLE)){ + if(FreqList[indx] == freq){ + mcuDsense = FM_MCU_DESE_ENABLE; + *freqavoid = 1; + } + indx++; + } + + if(mcuDsense == FM_MCU_DESE_DISABLE){ + if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)){ + ret = 0; + }else{ + ret = -FM_ELINK; + } + }else if(mcuDsense == FM_MCU_DESE_ENABLE){ + if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)){ + ret = 0; + }else{ + ret = -FM_ELINK; + } + }else{ + WCN_DBG(FM_ERR | CHIP,"para error!\n"); + ret = -FM_EPARA; + } + + WCN_DBG(FM_NTC | CHIP,"-%s, [mcuDsense=%d][ret=%d]\n", __func__, (fm_s32)mcuDsense, ret); + return ret; +} + +/*********************************************************************** +* TX PWR CTRL +* +***********************************************************************/ +fm_s32 MT6620_TX_PWR_CTRL(fm_u16 freq, fm_s32 *ctr) +{ + #define MT6620_TX_PWR_LEV_MAX 120 + #define MT6620_TX_PWR_LEV_MIN 85 + fm_s32 ret = 0; + fm_s32 tmp = 0; + fm_u16 reg = 0; + fm_u16 coarse; + fm_u16 fine; + + WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + if(freq < FM_TX_PWR_CTRL_FREQ_THR){ + //Power setting - 1dB, 3C(HEX)=A9E9 + *ctr -= 1; + }else{ + //Power setting -2 dB, 3C(HEX)=A8E9 + *ctr -= 2; + } + + if(*ctr > MT6620_TX_PWR_LEV_MAX){ + *ctr = MT6620_TX_PWR_LEV_MAX; + }else if(*ctr < MT6620_TX_PWR_LEV_MIN){ + *ctr = MT6620_TX_PWR_LEV_MIN; + } + fine = 43017 + ((1<<((*ctr-85)%6))-1)*32; + WCN_DBG(FM_DBG | CHIP,"0x3C = 0x%04x \n", fine); + coarse = 514 + ((1<<((*ctr-85)/6))-1)*4; + WCN_DBG(FM_DBG | CHIP,"0x3D = 0x%04x \n", coarse); + + if((ret = mt6620_write(0x3C, fine))) + goto out; + if((ret = mt6620_write(0x3D, coarse))) + goto out; + + tmp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); + if((ret = mt6620_read(0x9C, ®))) + goto out; + reg &= 0xC0FF; + if(tmp < FM_TX_PWR_CTRL_TMP_THR_DOWN){ + reg |= (0x1C << 8); //9CH, D13~D8 = 1C + }else if(tmp > FM_TX_PWR_CTRL_TMP_THR_UP){ + reg |= (0x33 << 8); //9CH, D13~D8 ==33 + }else{ + reg |= (0x25 << 8); //9CH, D13~D8 =25 + } + if((ret = mt6620_write(0x9C, reg))) + goto out; + +out: + WCN_DBG(FM_NTC | CHIP,"-%s, [temp=%d][ret=%d]\n", __func__, (fm_s32)tmp, ret); + return ret; +} + +/*********************************************************************** +* TX RTC PWR CTRL +* +***********************************************************************/ +fm_s32 MT6620_RTC_Drift_CTRL(fm_u16 freq, fm_s32 *ctr) +{ + fm_s32 ret = 0; + fm_u16 reg = 0; + fm_s32 chanel_resolution = 1; + fm_s16 compensation_int16 = 0; + fm_s32 tmp = 0; + fm_s32 drift = *ctr; + + WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + //turn off VCO tracking + if((ret = mt6620_set_bits(0x48, 0, MASK(15))))//set 48 D15=0 + goto out; + + //get channel resolution + if((ret = mt6620_read(0x46, ®))) + goto out; + reg &= 0xC000; + switch(reg >> 14){ + case 0: + chanel_resolution = 1024; + break; + case 1: + chanel_resolution = 512; + break; + case 2: + chanel_resolution = 256; + break; + case 3: + chanel_resolution = 128; + break; + default: + WCN_DBG(FM_ERR | CHIP,"chanel_resolution error[%d]\n", (fm_s32)(reg >> 14)); + break; + } + + //caculate and applye compensation + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + WCN_DBG(FM_DBG | CHIP,"[resolution=%d][freq=%d][drift=%d]\n", chanel_resolution, (fm_s32)(freq/100), (*ctr)); + tmp = (2*drift*(freq/100))/chanel_resolution; + compensation_int16 = (fm_s16)tmp; + if(compensation_int16 >= 511){ + compensation_int16 = 511; + }else if(compensation_int16 <= -512){ + compensation_int16 = -512; + } + if((ret = mt6620_read(0x47, ®))) + goto out; + reg &= 0x003F; + reg |= (compensation_int16 << 6); + if((ret = mt6620_write(0x47, reg))) + goto out; + + /* + //turn on VCO tracking + if((ret = mt6620_set_bits(0x48, BITn(15), MASK(15))))//set 48 D15=1 + goto out; + */ +out: + WCN_DBG(FM_NTC | CHIP,"-%s, [compensation=%d][ret=%d]\n", __func__, (fm_s32)(compensation_int16), ret); + return ret; +} + +/*********************************************************************** +* TX desense with WIFI/BT +* +***********************************************************************/ +fm_s32 MT6620_TX_DESENSE(fm_u16 freq, fm_s32 *ctr) +{ + fm_s32 ret = 0; + fm_u16 dataRead = 0; + fm_u16 tmp = 0; + + WCN_DBG(FM_DBG|CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq); + + // enable FM TX VCO tracking + if((ret = mt6620_read(0x29, &dataRead)))//read 29 + goto out; + WCN_DBG(FM_NTC | CHIP,"Before VCO On, [0x29=0x%04x]\n", dataRead); + if((ret = mt6620_read(0x12, &dataRead)))//read 12 + goto out; + WCN_DBG(FM_NTC | CHIP,"Before VCO On, [0x12=0x%04x]\n", dataRead); + + if((ret = mt6620_set_bits(0x12, 0, MASK(15))))//set 12 D15=0 + goto out; + if((ret = mt6620_set_bits(0x41, BITn(0), MASK(0))))//set 41 D0=1 + goto out; + if((ret = mt6620_set_bits(0x48, BITn(15), MASK(15))))//set 48 D15=1 + goto out; + + // wait 100ms (VCO tracking 100ms) + if(*ctr > FM_TX_TRACKING_TIME_MAX){ + *ctr = FM_TX_TRACKING_TIME_MAX; + } + Delayms(*ctr); + + // disable FM TX VCO tracking + if((ret = mt6620_set_bits(0x28, BITn(2), MASK(2))))//set 28 D2=1 + goto out; + if((ret = mt6620_read(0x29, &dataRead)))//read 29 D11~D0 + goto out; + WCN_DBG(FM_NTC | CHIP,"Before VCO Off, [0x29=0x%04x]\n", dataRead); + tmp = dataRead&0x0FFF; // Read 0x29 D11~D0 + if((ret = mt6620_read(0x12, &dataRead)))//read 12 + goto out; + //Set 0x12 D15 to 1, D11:D0 to read(0x29 D11~D0) + dataRead &= 0xF000; + dataRead |= tmp; + dataRead |= 1<<15; + if((ret = mt6620_write(0x12, dataRead))) + goto out; + WCN_DBG(FM_NTC | CHIP,"Before VCO Off, [0x12=0x%04x]\n", dataRead); + if((ret = mt6620_set_bits(0x48, 0, MASK(15))))//set 48 D15=0 + goto out; + if((ret = mt6620_set_bits(0x41, 0, MASK(0))))//set 41 D0=0 + goto out; + +out: + WCN_DBG(FM_DBG | CHIP,"-%s, [freq=%d][delay=%dms][ret=%d]\n", __func__, (fm_s32)freq, *ctr, ret); + return ret; +} + +static fm_s32 MT6620_Rds_Tx_Enable(void) +{ + mt6620_write(0x9F, 0x0000); + mt6620_write(0xAB, 0x3872); + mt6620_write(0xAC, 0x3B3A); + mt6620_write(0xAD, 0x0113); + mt6620_write(0xAE, 0x03B2); + mt6620_write(0xAF, 0x0001); + mt6620_write(0xB1, 0x63EB); + mt6620_write(0xF4, 0x0020); + mt6620_write(0xF5, 0x3222); + + return 0; +} + +static fm_s32 MT6620_Rds_Tx_Disable(void) +{ + mt6620_write(0x9F, 0x0000); + mt6620_write(0xAB, 0x39B6); + mt6620_write(0xAC, 0x3C3E); + mt6620_write(0xAD, 0x0000); + mt6620_write(0xAE, 0x03C2); + mt6620_write(0xAF, 0x0001); + mt6620_write(0xF4, 0x0020); + mt6620_write(0xF5, 0xBF16); + mt6620_write(0xB1, 0x623D); + + return 0; +} + +static fm_s32 MT6620_Rds_Tx(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt) +{ + fm_s32 ret = 0; + fm_u16 pkt_size = 0; + + WCN_DBG(FM_NTC | RDSC, "+%s():PI=0x%04x, PS=0x%04x/0x%04x/0x%04x, other_rds_cnt=%d \n",__func__, pi, ps[0], ps[1], ps[2], other_rds_cnt); + if (FM_LOCK(cmd_buf_lock)) + return (-FM_ELOCK); + pkt_size = mt6620_rds_tx(cmd_buf, TX_BUF_SIZE, pi, ps, other_rds, other_rds_cnt); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RDS_TX, SW_RETRY_CNT, RDS_TX_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c new file mode 100755 index 000000000000..48ddd35d59df --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c @@ -0,0 +1,470 @@ +/* mt6620_fm_link.c + * + * (C) Copyright 2011 + * MediaTek + * Hongcheng + * + * MT6620 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if 0 +#include +#include + +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +#include "mt6620_fm.h" +#include "mt6620_fm_link.h" +static struct fm_link_event *link_event; + +static struct fm_trace_fifo_t *cmd_fifo; + +static struct fm_trace_fifo_t *evt_fifo; + +static fm_s32 (*reset)(fm_s32 sta) = NULL; + +static void mt6620_fm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, + ENUM_WMTMSG_TYPE_T type, + void *buf, + unsigned int sz) +{ + //To handle reset procedure please + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((char *)&rst_msg, (char *)buf, sz); + WCN_DBG(FM_WAR | LINK, "[src=%d], [dst=%d], [type=%d], [buf=0x%x], [sz=%d], [max=%d]\n", src, dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_FM) && (type == WMTMSG_TYPE_RESET)) { + if (rst_msg == WMTRSTMSG_RESET_START) { + WCN_DBG(FM_WAR | LINK, "FM restart start!\n"); + if (reset) { + reset(1); + } + + } else if (rst_msg == WMTRSTMSG_RESET_END) { + WCN_DBG(FM_WAR | LINK, "FM restart end!\n"); + if (reset) { + reset(0); + } + } + } + } else { + /*message format invalid*/ + WCN_DBG(FM_WAR | LINK, "message format invalid!\n"); + } +} + + +fm_s32 fm_link_setup(void* data) +{ + fm_s32 ret = 0; + + if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) { + WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n"); + return -1; + } + + link_event->ln_event = fm_flag_event_create("ln_evt"); + + if (!link_event->ln_event) { + WCN_DBG(FM_ALT | LINK, "create mt6620_ln_event failed\n"); + fm_free(link_event); + return -1; + } + + fm_flag_event_get(link_event->ln_event); + + + WCN_DBG(FM_NTC | LINK, "fm link setup\n"); + + cmd_fifo = fm_trace_fifo_create("cmd_fifo"); + if (!cmd_fifo) { + WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n"); + ret = -1; + goto failed; + } + + evt_fifo = fm_trace_fifo_create("evt_fifo"); + if (!evt_fifo) { + WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n"); + ret = -1; + goto failed; + } + + reset = data; // get whole chip reset cb + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, mt6620_fm_wholechip_rst_cb); + return 0; + +failed: + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + return ret; +} + +fm_s32 fm_link_release(void) +{ + + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + WCN_DBG(FM_NTC | LINK, "fm link release\n"); + return 0; +} + +/* + * fm_ctrl_rx + * the low level func to read a rigister + * @addr - rigister address + * @val - the pointer of target buf + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val) +{ + return 0; +} + +/* + * fm_ctrl_tx + * the low level func to write a rigister + * @addr - rigister address + * @val - value will be writed in the rigister + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val) +{ + return 0; +} + +/* + * fm_cmd_tx() - send cmd to FM firmware and wait event + * @buf - send buffer + * @len - the length of cmd + * @mask - the event flag mask + * @ cnt - the retry conter + * @timeout - timeout per cmd + * Return 0, if success; error code, if failed + */ +fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result)) +{ + fm_s32 ret_time = 0; + struct task_struct *task = current; + struct fm_trace_t trace; + + if ((NULL == buf) || (len < 0) || (0 == mask) + || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) { + WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n"); + return -FM_EPARA; + } + + FM_EVENT_CLR(link_event->ln_event, mask); + +#ifdef FM_TRACE_ENABLE + trace.type = buf[0]; + trace.opcode = buf[1]; + trace.len = len - 4; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len); +#endif + +sw_retry: + +#ifdef FM_TRACE_ENABLE + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + + //send cmd to FM firmware + if (mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX) <= 0) { + WCN_DBG(FM_EMG | LINK, "send data over stp failed\n"); + return -FM_ELINK; + } + + //wait the response form FM firmware + ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout); + + if (!ret_time) { + if (0 < cnt--) { + WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid); + fm_print_cmd_fifo(); + fm_print_evt_fifo(); + return -FM_EFW; + goto sw_retry; //retry if timeout and retry cnt > 0 + } else { + WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n"); + return -FM_EFW; + } + } + + FM_EVENT_CLR(link_event->ln_event, mask); + + if (callback) { + callback(&link_event->result); + } + + return 0; +} + +fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32)) +{ + fm_s32 len; + fm_s32 i = 0; + fm_u8 opcode = 0; + fm_u16 length = 0; + fm_u8 ch; + fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps + static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE; + struct fm_trace_t trace; + struct task_struct *task = current; + + len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX); + WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]); + + while (i < len) { + ch = rx_buf[i]; + + switch (state) { + case FM_TASK_RX_PARSER_PKT_TYPE: + + if (ch == FM_TASK_EVENT_PKT_TYPE) { + if ((i + 5) < RX_BUF_SIZE) { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]); + } else { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]); + } + + state = FM_TASK_RX_PARSER_OPCODE; + } else { + WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch); + } + + i++; + break; + + case FM_TASK_RX_PARSER_OPCODE: + i++; + opcode = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_1; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_1: + i++; + length = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_2; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_2: + i++; + length |= (fm_u16)(ch << 0x8); + +#ifdef FM_TRACE_ENABLE + trace.type = FM_TASK_EVENT_PKT_TYPE; + trace.opcode = opcode; + trace.len = length; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length); + + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + if (length > 0) { + state = FM_TASK_RX_PARSER_PKT_PAYLOAD; + } else { + state = FM_TASK_RX_PARSER_PKT_TYPE; + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + } + + break; + + case FM_TASK_RX_PARSER_PKT_PAYLOAD: + + switch (opcode) { + case FM_TUNE_OPCODE: + + if ((length == 1) && (rx_buf[i] == 1)) { + FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE); + } + + break; + + case FM_SOFT_MUTE_TUNE_OPCODE: + + if (length >= 2) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length); + FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE); + } + break; + + case FM_SEEK_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz + } + + FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE); + break; + + case FM_SCAN_OPCODE: + + //check if the result data is long enough + if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) { + WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + return 0; + } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE); + } else { + fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + } + + break; + + case FSPI_READ_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8)); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + case RDS_RX_DATA_OPCODE: + + //check if the rds data is long enough + if ((RX_BUF_SIZE - i) < length) { + WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + //copy rds data to rds buf + fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length); + + /*Handle the RDS data that we get*/ + if (rds_parser) { + rds_parser(&link_event->result.rds_rx_result, length); + } else { + WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n"); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + default: + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + state = FM_TASK_RX_PARSER_PKT_TYPE; + i += length; + break; + + default: + break; + } + } + + return 0; +} + +fm_bool fm_wait_stc_done(fm_u32 sec) +{ + return fm_true; +} + +fm_s32 fm_force_active_event(fm_u32 mask) +{ + fm_u32 flag; + + flag = FM_EVENT_GET(link_event->ln_event); + WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag); + flag = FM_EVENT_SEND(link_event->ln_event, mask); + WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag); + + return 0; +} + + +extern fm_s32 fm_print_cmd_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(cmd_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "trace\n"); + } +#endif + + return 0; +} + +extern fm_s32 fm_print_evt_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(evt_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(evt_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name); + } +#endif + + return 0; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c new file mode 100755 index 000000000000..27e572996629 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c @@ -0,0 +1,363 @@ +/* mt6620_rds.c + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * mt6620 FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" +#include "mt6620_fm_reg.h" + + +#define MT6620_RDS_BLER_TH1 90 +#define MT6620_RDS_BLER_TH2 60 +#define MT6620_RDS_BLER_C1 12 +#define MT6620_RDS_BLER_C2 6 +#define MT6620_RDS_BLER_T1 5000 +#define MT6620_RDS_BLER_T2 5000 + +static fm_bool bRDS_FirstIn = fm_false; +static fm_u32 gBLER_CHK_INTERVAL = 5000; +static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0; +static fm_u8 BAD_BLK_RATIO = 0; + +static struct fm_callback *fm_cb = NULL; +static struct fm_basic_interface *fm_bi = NULL; + +//static fm_bool mt6620_RDS_support(void); +static fm_s32 mt6620_RDS_enable(void); +static fm_s32 mt6620_RDS_disable(void); +static fm_u16 mt6620_RDS_Get_GoodBlock_Counter(void); +static fm_u16 mt6620_RDS_Get_BadBlock_Counter(void); +static fm_u8 mt6620_RDS_Get_BadBlock_Ratio(void); +static fm_u32 mt6620_RDS_Get_BlerCheck_Interval(void); +static void mt6620_RDS_Init_Data(rds_t *pstRDSData); + +#if 0 +static fm_bool mt6620_RDS_support(void) +{ + return fm_true; +} +#endif +static fm_s32 mt6620_RDS_enable(void) +{ + fm_u16 page; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); //sleect page3 + + fm_bi->write(0xCB, 0xE016); + + fm_bi->write(FM_MAIN_PGSEL, 0x0000); //sleect page0 + + fm_bi->write(0x63, 0x0491); + fm_bi->setbits(0x6B, 0x2000, 0xFFFF); + + fm_bi->write(FM_MAIN_PGSEL, page); //recover page + return 0; +} + +static fm_s32 mt6620_RDS_disable(void) +{ + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + fm_bi->setbits(0x6B, 0x0000, 0xDFFF); + fm_bi->write(0x63, 0x0481); + + return 0; +} + +static fm_u16 mt6620_RDS_Get_GoodBlock_Counter(void) +{ + fm_u16 tmp_reg; + fm_u16 page; + + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); + + fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + + fm_bi->write(FM_MAIN_PGSEL, page); + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u16 mt6620_RDS_Get_BadBlock_Counter(void) +{ + fm_u16 tmp_reg; + fm_u16 page; + + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); + + fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + + fm_bi->write(FM_MAIN_PGSEL, page); + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u8 mt6620_RDS_Get_BadBlock_Ratio(void) +{ + fm_u16 tmp_reg; + fm_u16 gbc; + fm_u16 bbc; + + gbc = mt6620_RDS_Get_GoodBlock_Counter(); + bbc = mt6620_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) { + tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc)); + } else { + tmp_reg = 0; + } + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_s32 mt6620_RDS_BlockCounter_Reset(void) +{ + fm_u16 page; + + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); + + fm_bi->write(0xC8, 0x0001); + fm_bi->write(0xC8, 0x0002); + + fm_bi->write(FM_MAIN_PGSEL, page); + + return 0; +} + +static fm_u32 mt6620_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static fm_s32 mt6620_RDS_Reset(void) +{ + fm_u16 page; + + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); + + fm_bi->write(0xB0, 0x0001); + + fm_bi->write(FM_MAIN_PGSEL, page); + + return 0; +} + +static fm_s32 mt6620_RDS_Reset_Block(void) +{ + fm_u16 page; + + fm_bi->read(FM_MAIN_PGSEL, &page); + fm_bi->write(FM_MAIN_PGSEL, 0x0003); + + fm_bi->write(0xDD, 0x0001); + + fm_bi->write(FM_MAIN_PGSEL, page); + + return 0; +} + +static fm_s32 mt6620_RDS_BlerCheck(rds_t *dst) +{ + fm_s32 ret = 0; + fm_u16 TOTAL_CNT; + static fm_u16 RDS_Sync_Cnt; + static fm_u16 RDS_Block_Reset_Cnt; +#if 0 + if (dst->AF_Data.Addr_Cnt == 0xFF) { + //AF List Finished + dst->event_status |= RDS_EVENT_AF; //Need notfiy application + //loop dst->event_status then act + if (dst->event_status != 0) { + //fm->RDS_Data_ready = true; + //wake_up_interruptible(&fm->read_wait); + //FIXME + WCN_DBG(FM_DBG | RDSC, "RDS_EVENT_AF, trigger read\n"); + } + } +#endif + gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T1; + GOOD_BLK_CNT = mt6620_RDS_Get_GoodBlock_Counter(); + BAD_BLK_CNT = mt6620_RDS_Get_BadBlock_Counter(); + TOTAL_CNT = GOOD_BLK_CNT + BAD_BLK_CNT; + + mt6620_RDS_BlockCounter_Reset(); + + if ((GOOD_BLK_CNT == 0) && (BAD_BLK_CNT == 0)) { + BAD_BLK_RATIO = 0; + } else { + BAD_BLK_RATIO = (BAD_BLK_CNT * 100) / TOTAL_CNT; + } + + if ((BAD_BLK_RATIO < MT6620_RDS_BLER_TH2) && (RDS_Sync_Cnt > MT6620_RDS_BLER_C1)) { + gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2; + + if (RDS_Block_Reset_Cnt > 1) + RDS_Block_Reset_Cnt--; + } else { + if (BAD_BLK_RATIO > MT6620_RDS_BLER_TH1) { + //>90% + mt6620_RDS_BlockCounter_Reset(); + RDS_Sync_Cnt = 0; //need clear or not, Question, LCH. + RDS_Block_Reset_Cnt++; + + if ((RDS_Block_Reset_Cnt > MT6620_RDS_BLER_C2) || bRDS_FirstIn) { + if (bRDS_FirstIn) + bRDS_FirstIn = false; + + if ((ret = mt6620_RDS_Reset())) + return ret; + + RDS_Block_Reset_Cnt = 0; + WCN_DBG(FM_DBG | RDSC, "RDS Reset, blk_cnt:%d, RDS_FirstIn:%d\n", RDS_Block_Reset_Cnt, bRDS_FirstIn); + } else if (TOTAL_CNT > 12) { + //LCH question 2, why 12??? + WCN_DBG(FM_DBG | RDSC, "RDS Block Reset: %x\n", RDS_Block_Reset_Cnt); + + if ((ret = mt6620_RDS_Reset_Block())) + return ret; + } + } else { + RDS_Sync_Cnt++; //(60%-90%) + WCN_DBG(FM_DBG | RDSC, "RDS Sync Cnt: %d\n", RDS_Block_Reset_Cnt); + + if (RDS_Block_Reset_Cnt > 1) + RDS_Block_Reset_Cnt--; + + if (RDS_Sync_Cnt > MT6620_RDS_BLER_C1) { + gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2; + } + } + } + + return ret; +} + +static void mt6620_RDS_Init_Data(rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0 , sizeof(rds_t)); + bRDS_FirstIn = fm_true; + + fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData)); + fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS)); + fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON)); +} + +fm_bool mt6620_RDS_OnOff(rds_t *dst, fm_bool bFlag) +{ +#if 0 + if (mt6620_RDS_support() == fm_false) { + WCN_DBG(FM_ALT | RDSC, "mt6620_RDS_OnOff failed, RDS not support\n"); + return fm_false; + } +#endif + if (bFlag) { + mt6620_RDS_Init_Data(dst); + mt6620_RDS_enable(); + } else { + mt6620_RDS_disable(); + } + + return fm_true; +} + +DEFINE_RDSLOG(mt6620_rds_log); + +/* mt6620_RDS_Efm_s32_Handler - response FM RDS interrupt + * @fm - main data structure of FM driver + * This function first get RDS raw data, then call RDS spec parser + */ +static fm_s32 mt6620_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)) +{ + mt6620_rds_log.log_in(&mt6620_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static fm_s32 mt6620_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len) +{ + return mt6620_rds_log.log_out(&mt6620_rds_log, dst, dst_len); +} + +static fm_s32 mt6620_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static fm_s32 mt6620_rds_gc_reset(rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +fm_s32 MT6620fm_rds_ops_register(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + FMR_ASSERT(ops->bi.write); + FMR_ASSERT(ops->bi.read); + FMR_ASSERT(ops->bi.setbits); + FMR_ASSERT(ops->bi.usdelay); + fm_bi = &ops->bi; + + FMR_ASSERT(ops->cb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb = &ops->cb; + + ops->ri.rds_blercheck = mt6620_RDS_BlerCheck; + ops->ri.rds_onoff = mt6620_RDS_OnOff; + ops->ri.rds_parser = mt6620_rds_parser; + ops->ri.rds_gbc_get = mt6620_RDS_Get_GoodBlock_Counter; + ops->ri.rds_bbc_get = mt6620_RDS_Get_BadBlock_Counter; + ops->ri.rds_bbr_get = mt6620_RDS_Get_BadBlock_Ratio; + ops->ri.rds_bc_reset = mt6620_RDS_BlockCounter_Reset; + ops->ri.rds_bci_get = mt6620_RDS_Get_BlerCheck_Interval; + ops->ri.rds_log_get = mt6620_rds_log_get; + ops->ri.rds_gc_get = mt6620_rds_gc_get; + ops->ri.rds_gc_reset = mt6620_rds_gc_reset; + return ret; +} + +fm_s32 MT6620fm_rds_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + + fm_bi = NULL; + fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h new file mode 100755 index 000000000000..f333f7edda4b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h @@ -0,0 +1,10639 @@ + +const unsigned char channel_parameter[] = { +0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,5 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,1 +,0 +,0 +,0 +}; + +#if defined(MT6626_FPGA) +const unsigned short bin_rom[] = { +0x0000 +,0x1FFF +,0xBC00 +,0x0010 +,0xBC00 +,0x0271 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0xBC02 +,0x0906 +,0xBC20 +,0x2019 +,0x4021 +,0xFB11 +,0xBC02 +,0x0807 +,0xBC20 +,0x2019 +,0x4041 +,0xFB11 +,0xBC22 +,0x0480 +,0xBC20 +,0x0080 +,0x4001 +,0x8B02 +,0xE401 +,0xBC21 +,0x0367 +,0xA301 +,0x0080 +,0xBC20 +,0x201A +,0x41E1 +,0xFA12 +,0xA302 +,0x0082 +,0x0891 +,0x2620 +,0x8FF9 +,0x3D02 +,0xBC21 +,0x2018 +,0x481E +,0xBC22 +,0x2019 +,0x8C69 +,0x40C0 +,0xA203 +,0x0082 +,0x2631 +,0x8F4B +,0x2634 +,0x8F3E +,0x2632 +,0x8F1D +,0xB306 +,0x0008 +,0x8F0A +,0x40E0 +,0xFB50 +,0xBC02 +,0x1E58 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8C53 +,0x40C0 +,0xFB50 +,0xFA33 +,0x26B0 +,0x8F08 +,0xBC02 +,0x072A +,0xBC21 +,0x2018 +,0x4020 +,0x7207 +,0xBB30 +,0x40C0 +,0xBC22 +,0x2019 +,0xA31E +,0x0082 +,0x8D41 +,0x40A0 +,0x70E0 +,0x3B50 +,0xBC21 +,0x201D +,0xBC22 +,0x201B +,0xFA31 +,0xFA52 +,0x0810 +,0xBC3E +,0x00E4 +,0xBC3A +,0x0692 +,0xB400 +,0x0002 +,0xA31E +,0x0083 +,0xA31A +,0x0084 +,0x0408 +,0xBC02 +,0x0131 +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8D23 +,0x4080 +,0xFB50 +,0xBC02 +,0x016B +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8D18 +,0x4060 +,0xBC21 +,0x201F +,0xFB50 +,0xFA30 +,0xBC3E +,0x00C8 +,0xBC3A +,0x0652 +,0xBC21 +,0x03FF +,0xA31E +,0x0083 +,0xA31A +,0x0084 +,0x0801 +,0xBC02 +,0x0131 +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0xA203 +,0x0082 +,0xB316 +,0x0040 +,0x8F91 +,0xBC00 +,0x001C +,0x6915 +,0xA902 +,0x8E00 +,0xA30E +,0x0085 +,0xDFD5 +,0xBC02 +,0x0607 +,0xBC02 +,0x077A +,0xBC20 +,0x2019 +,0x7040 +,0x4FD5 +,0xBC22 +,0x2008 +,0xFB11 +,0xFA51 +,0xBC23 +,0x4000 +,0x0ACB +,0xBC21 +,0x2100 +,0xFB53 +,0xFA32 +,0xB314 +,0x0020 +,0x8FFB +,0x4121 +,0xE9FE +,0xFB11 +,0xBC00 +,0x1D52 +,0xE902 +,0xBC20 +,0x2019 +,0x7060 +,0x5FD5 +,0x8C02 +,0xFB11 +,0x8E00 +,0xA200 +,0x008B +,0x2600 +,0x8FFA +,0x3E02 +,0xA200 +,0x008C +,0x6980 +,0x4FD5 +,0x8F02 +,0xA200 +,0x0086 +,0x2681 +,0x8F02 +,0x4080 +,0xA300 +,0x0082 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0xBC20 +,0x2019 +,0x7068 +,0x5FD5 +,0x8C02 +,0xFB11 +,0x8E00 +,0xA200 +,0x008B +,0x2600 +,0x8FFA +,0x3E02 +,0xA200 +,0x008C +,0xA201 +,0x0088 +,0x2681 +,0x8F06 +,0x4020 +,0xA202 +,0x008A +,0x1401 +,0x0A10 +,0xA300 +,0x008A +,0x3409 +,0xA300 +,0x0088 +,0xA201 +,0x0086 +,0xB300 +,0x0010 +,0x8F01 +,0x2691 +,0x8F09 +,0x401C +,0xBC20 +,0x2041 +,0xA202 +,0x008A +,0xA31C +,0x0088 +,0xA31C +,0x008A +,0xFB12 +,0x2691 +,0x8F16 +,0xBC20 +,0x2019 +,0x41C1 +,0x7008 +,0x7B11 +,0xBC22 +,0x2018 +,0xBC20 +,0x201A +,0x8C05 +,0xFB51 +,0x8E00 +,0xBC20 +,0x201A +,0x8E00 +,0xFA10 +,0xB310 +,0x0008 +,0x8FF6 +,0x7040 +,0x0FD5 +,0x8C03 +,0xA300 +,0x0082 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x05A2 +,0xA200 +,0x0087 +,0x2680 +,0x8F0C +,0xBC20 +,0x2040 +,0x7000 +,0x4FC3 +,0x700F +,0xBB11 +,0x4042 +,0xA303 +,0x0089 +,0xA31E +,0x0087 +,0xA301 +,0x0086 +,0xFB12 +,0xA200 +,0x0084 +,0x8EA0 +,0xBC20 +,0x02C7 +,0xA300 +,0x009B +,0xBC02 +,0x00A7 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x033D +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7000 +,0x4FF5 +,0xBC22 +,0x201A +,0x7040 +,0x3B11 +,0xFA51 +,0x2248 +,0x8F00 +,0xA300 +,0x0082 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0480 +,0xBC20 +,0x02B3 +,0xA300 +,0x009B +,0xBC02 +,0x00A7 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x03F7 +,0xBC22 +,0x2018 +,0x7008 +,0x3B11 +,0x7050 +,0x3B50 +,0xBC21 +,0x2019 +,0x8C2E +,0xFB30 +,0xA200 +,0x0081 +,0x2601 +,0x8F04 +,0xBC21 +,0x8000 +,0xBC20 +,0x2023 +,0x8C24 +,0xFB11 +,0xBC02 +,0x01BE +,0xA200 +,0x0085 +,0x4001 +,0xA301 +,0x0081 +,0x2682 +,0x8F02 +,0x4100 +,0xA300 +,0x0082 +,0xBC02 +,0x1E58 +,0xBC20 +,0x201A +,0x8E00 +,0xFA10 +,0xB310 +,0x0008 +,0x8F05 +,0xBC20 +,0x2019 +,0x4161 +,0x7008 +,0x3B11 +,0xA300 +,0x0085 +,0xBC02 +,0x077A +,0xBC20 +,0x2023 +,0xBC21 +,0x8000 +,0xFB11 +,0xA200 +,0x0082 +,0x2604 +,0x8FCE +,0x3E02 +,0x7000 +,0x4FD5 +,0xBC20 +,0x2008 +,0x8EC0 +,0xE9FE +,0xFB11 +,0xE902 +,0xA200 +,0x0098 +,0x6CE0 +,0x1FD5 +,0x8F57 +,0xBC02 +,0x0918 +,0xBC20 +,0x01AE +,0xBC02 +,0x09F0 +,0xA200 +,0x02A7 +,0x2682 +,0x8F02 +,0xBC20 +,0x01AE +,0xBC02 +,0x0D50 +,0xA200 +,0x008E +,0x2606 +,0x8F1E +,0x2604 +,0x8F17 +,0x2602 +,0x8F0B +,0x2600 +,0x8F05 +,0xA200 +,0x008D +,0x2680 +,0x8F20 +,0xBC02 +,0x0BDE +,0x8D1F +,0xBC02 +,0x0E6E +,0x8D1C +,0xBC20 +,0x2032 +,0x4101 +,0xFA10 +,0x0801 +,0xA300 +,0x01E3 +,0xBC02 +,0x0A17 +,0x8D12 +,0xBC02 +,0x0AA2 +,0xBC02 +,0x0CA4 +,0x8D0D +,0xA200 +,0x0085 +,0x2601 +,0x8F05 +,0xA200 +,0x02C7 +,0x2601 +,0x8F01 +,0xBC02 +,0x0B48 +,0x8D02 +,0xBC02 +,0x0B2B +,0xA201 +,0x01BE +,0xBC20 +,0x01AE +,0xBC02 +,0x0A72 +,0xBC20 +,0x01E7 +,0xBC02 +,0x0B04 +,0xA200 +,0x0266 +,0x2680 +,0xBC20 +,0x01E7 +,0x8F03 +,0xBC21 +,0x7FFF +,0xBC02 +,0x0B8C +,0x8D04 +,0xA201 +,0x01FF +,0xBC02 +,0x0B8C +,0xBC02 +,0x0C54 +,0xA200 +,0x0099 +,0x2600 +,0x8F02 +,0xBC02 +,0x195E +,0xBC02 +,0x1926 +,0xA200 +,0x009A +,0x2600 +,0x8F02 +,0xB000 +,0xFFFF +,0xA300 +,0x009A +,0xBC20 +,0x2040 +,0x4021 +,0xFA10 +,0x0801 +,0x2600 +,0x8F0A +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0xFA10 +,0x0801 +,0x2680 +,0x8F02 +,0xA200 +,0x009A +,0x2600 +,0x8F15 +,0x3E02 +,0x4000 +,0xA300 +,0x0099 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x0080 +,0xFA12 +,0x0851 +,0x2610 +,0x8F0B +,0xFA11 +,0xBC22 +,0xFF7F +,0x084A +,0x7000 +,0x3B11 +,0xBC02 +,0x05B3 +,0x8D03 +,0x4020 +,0xA300 +,0x0099 +,0x7038 +,0x4FD5 +,0xA200 +,0x008E +,0xE9FE +,0x3401 +,0x8EC0 +,0x0801 +,0xA300 +,0x008E +,0x4020 +,0xBC21 +,0x00C0 +,0xA300 +,0x0091 +,0xA300 +,0x0092 +,0xA301 +,0x0098 +,0x8EC0 +,0xA300 +,0x0090 +,0xA300 +,0x008F +,0xE918 +,0x8E00 +,0xDD05 +,0xBC25 +,0x2096 +,0xDD5B +,0xFAB5 +,0xA205 +,0x009B +,0xDD7A +,0xDD9F +,0xDDBE +,0xDDDD +,0xDDFC +,0xDE0B +,0xDE2C +,0xDE49 +,0xDE68 +,0xDE8F +,0xDEAE +,0xDED5 +,0xDEE6 +,0xDF04 +,0xDF23 +,0xDF42 +,0xDF61 +,0xDF80 +,0xDD27 +,0xF9FC +,0x8EA5 +,0xBC20 +,0x2096 +,0xBC21 +,0x00FF +,0xFA10 +,0x6220 +,0x4D05 +,0xA203 +,0x0096 +,0x6854 +,0xCD27 +,0x6624 +,0xCF80 +,0xA302 +,0x0096 +,0xCF61 +,0xCF42 +,0xCF23 +,0xCF04 +,0xCEE6 +,0xCDFC +,0xCDDD +,0xCDBE +,0xCD9F +,0xCD7A +,0xCD5B +,0xF8FC +,0xCED5 +,0xCEAE +,0xCE8F +,0xCE68 +,0xCE49 +,0xCE2C +,0xCE0B +,0xE9E8 +,0x8EC8 +,0xBC20 +,0x2102 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x6980 +,0x2902 +,0x8F07 +,0xDFD5 +,0xBC02 +,0x02DB +,0xBC20 +,0x02DB +,0xCFD5 +,0xA300 +,0x009B +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x2104 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x6980 +,0x2902 +,0x8F07 +,0xDFD5 +,0xBC02 +,0x0423 +,0xBC20 +,0x0423 +,0xCFD5 +,0xA300 +,0x009B +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE906 +,0xA202 +,0x0090 +,0x69A8 +,0x1F95 +,0x8F19 +,0xBC24 +,0x2081 +,0xBC23 +,0x2082 +,0xFA95 +,0xBC24 +,0x2015 +,0xFA73 +,0xA21A +,0x0461 +,0xA21E +,0x046B +,0xA210 +,0x0361 +,0xFA94 +,0xA305 +,0x02CA +,0xA303 +,0x02CB +,0xA310 +,0x02C8 +,0xA31A +,0x02C9 +,0xA304 +,0x02CC +,0xA31E +,0x02CD +,0x26A6 +,0x8F32 +,0xBC23 +,0x027F +,0xBC24 +,0x026F +,0x4022 +,0xBD10 +,0x0306 +,0xE205 +,0xE585 +,0xA21C +,0x02C8 +,0xA21A +,0x02CA +,0xA21E +,0x02CB +,0xA210 +,0x02C9 +,0xA205 +,0x02CC +,0xA203 +,0x02CD +,0xA204 +,0x0081 +,0xA31C +,0x02C2 +,0xA310 +,0x02C3 +,0xA31A +,0x02C4 +,0xA31E +,0x02C5 +,0xA305 +,0x02C6 +,0xA303 +,0x02C7 +,0x2640 +,0x8F03 +,0xA203 +,0x0095 +,0x34D9 +,0xA303 +,0x0095 +,0xA203 +,0x0098 +,0xA302 +,0x0081 +,0x3230 +,0x8F02 +,0xB026 +,0xFFFF +,0xA302 +,0x0098 +,0xA200 +,0x028F +,0x421E +,0x403A +,0xBC3C +,0x027F +,0xBC22 +,0x2033 +,0xE064 +,0xBC23 +,0x2034 +,0xE065 +,0xFB54 +,0xFB75 +,0xA300 +,0x028F +,0xBC02 +,0x1BC3 +,0xBC22 +,0x3105 +,0xA200 +,0x0313 +,0x700E +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2139 +,0xBC3C +,0x02E0 +,0xBD05 +,0x0352 +,0xFA53 +,0xE463 +,0xA202 +,0x0099 +,0x2620 +,0xA300 +,0x0313 +,0x385A +,0x8F10 +,0xBC23 +,0x2008 +,0xBC24 +,0x0080 +,0xFA75 +,0x0B2C +,0xBC25 +,0x2103 +,0xFB74 +,0xFAB3 +,0xBC24 +,0x4000 +,0x08DC +,0x2630 +,0x8F01 +,0xBC02 +,0x15BE +,0x4022 +,0xA203 +,0x0091 +,0x26B0 +,0x8F05 +,0xBC20 +,0x2012 +,0xBC21 +,0x2014 +,0xBC02 +,0x106C +,0x4022 +,0xA203 +,0x0093 +,0xB306 +,0x0011 +,0x4003 +,0x1893 +,0xA204 +,0x0091 +,0x6D28 +,0x5FA2 +,0x4244 +,0x2214 +,0x18DA +,0xA202 +,0x008F +,0x2620 +,0xA303 +,0x0091 +,0x8F67 +,0x2621 +,0x8F53 +,0x2622 +,0x8F2B +,0x26A3 +,0x8F26 +,0xBC02 +,0x118C +,0xCFA2 +,0x2620 +,0xBC20 +,0x2015 +,0x8F0E +,0xA201 +,0x0097 +,0xBC02 +,0x101D +,0xBC02 +,0x1391 +,0xBC02 +,0x1DAA +,0xA202 +,0x0097 +,0x2622 +,0x4043 +,0x8F00 +,0x34D1 +,0xA303 +,0x0097 +,0xA202 +,0x0093 +,0x3511 +,0x4242 +,0x21E2 +,0xA203 +,0x0094 +,0x4005 +,0x34D9 +,0x192C +,0x4062 +,0x08DA +,0xA304 +,0x0093 +,0x8C51 +,0xA303 +,0x0094 +,0x8C4E +,0x4062 +,0x3854 +,0xB004 +,0xFFFB +,0xDFC0 +,0xBC02 +,0x121B +,0x6E15 +,0x0FC0 +,0xB014 +,0xFFFA +,0xDFC1 +,0xBC02 +,0x1277 +,0xBC02 +,0x12BC +,0xCFC0 +,0xBC21 +,0x0464 +,0xBC02 +,0x1326 +,0x7018 +,0x8FA3 +,0x2630 +,0x8F33 +,0xA201 +,0x0097 +,0xBC20 +,0x2013 +,0xBC02 +,0x1037 +,0xA201 +,0x0097 +,0xBC20 +,0x200B +,0xBC02 +,0x1092 +,0x4062 +,0x8D27 +,0xBC02 +,0x118C +,0xBC02 +,0x11E4 +,0xBC02 +,0x1B03 +,0x7018 +,0x8FA3 +,0x2630 +,0x8F1B +,0xA201 +,0x0097 +,0xBC20 +,0x2011 +,0xBC02 +,0x10B6 +,0x4062 +,0x8D15 +,0xBC02 +,0x12BC +,0xCFA2 +,0x2620 +,0x8F00 +,0xBC02 +,0x1E00 +,0xBC02 +,0x10FF +,0xA202 +,0x0094 +,0x26A0 +,0x4062 +,0x8F05 +,0xA203 +,0x047B +,0x2630 +,0x8F01 +,0xBC02 +,0x115E +,0x4062 +,0xA204 +,0x008F +,0xA203 +,0x0090 +,0x6D48 +,0x4F95 +,0x34D9 +,0x40E6 +,0xA205 +,0x008D +,0x08DE +,0x08A2 +,0x26D0 +,0xA303 +,0x0090 +,0xA302 +,0x008F +,0x8F04 +,0xBC22 +,0x31F8 +,0xDF95 +,0xFA52 +,0x8EA2 +,0xCF95 +,0x8E00 +,0x8EC0 +,0xE9FA +,0x8E00 +,0xE902 +,0xA200 +,0x0092 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x10DC +,0xCFC0 +,0xB300 +,0x0044 +,0x8F2B +,0xA201 +,0x0097 +,0xB300 +,0x0045 +,0x8F21 +,0xB300 +,0x0046 +,0x8F14 +,0xCFC0 +,0xB310 +,0x0047 +,0x8F21 +,0xA200 +,0x0470 +,0x2680 +,0x8F00 +,0xBC02 +,0x0F91 +,0xBC02 +,0x1DAA +,0xA200 +,0x0097 +,0x2602 +,0x4041 +,0x8F00 +,0x3441 +,0xA301 +,0x0097 +,0x8D12 +,0xBC20 +,0x2013 +,0xBC02 +,0x1037 +,0xA201 +,0x0097 +,0xBC20 +,0x200B +,0xBC02 +,0x1092 +,0x8D07 +,0xBC20 +,0x2011 +,0xBC02 +,0x10B6 +,0x8D02 +,0xBC02 +,0x1E00 +,0x7240 +,0x4FC0 +,0x6D00 +,0x4FF5 +,0x21C1 +,0x4001 +,0x1808 +,0xA201 +,0x008D +,0x2690 +,0xA300 +,0x0092 +,0x8F04 +,0xBC20 +,0x31F8 +,0xDFD5 +,0xFA10 +,0x8EA0 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x009C +,0xBC21 +,0x047C +,0x0448 +,0x3489 +,0x32A0 +,0x4001 +,0x8F01 +,0x8B02 +,0xE401 +,0x8EB8 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0474 +,0xBC20 +,0x3173 +,0xBC21 +,0x3010 +,0xBC24 +,0x02A8 +,0xBC22 +,0x2032 +,0x7014 +,0x3A10 +,0x4085 +,0x700F +,0x3A31 +,0xA300 +,0x01E5 +,0xFA53 +,0xBC40 +,0x1605 +,0xA301 +,0x0467 +,0x4100 +,0xBC40 +,0x1E10 +,0xBC40 +,0x2610 +,0x6206 +,0x2610 +,0xFA51 +,0x6213 +,0x6650 +,0xBC3A +,0x0184 +,0xBC3E +,0x01C0 +,0x4503 +,0x4444 +,0xBC2E +,0x0160 +,0xBC2F +,0x0170 +,0xB048 +,0x009C +,0xB056 +,0x009C +,0xA300 +,0x01E3 +,0xA301 +,0x01F7 +,0xA31C +,0x0468 +,0xA31C +,0x0461 +,0xA31C +,0x045C +,0xA30E +,0x016E +,0xA30F +,0x017E +,0xA31A +,0x01AC +,0xA31A +,0x01AD +,0xA31E +,0x01E0 +,0xA31E +,0x01E1 +,0xA304 +,0x015E +,0xA305 +,0x015F +,0xBC20 +,0x3136 +,0xBC21 +,0x3163 +,0xBD04 +,0x04D2 +,0xFA04 +,0xFB24 +,0xFA0C +,0xFB24 +,0xBD04 +,0x04D8 +,0xFA0C +,0xFB24 +,0xBC20 +,0x31B2 +,0x7717 +,0xBA51 +,0x7006 +,0xBA14 +,0x38BC +,0x084D +,0xB048 +,0x319C +,0xA301 +,0x0266 +,0xBC20 +,0x0200 +,0xFA91 +,0xB040 +,0x0050 +,0xB060 +,0x0010 +,0xA304 +,0x0261 +,0xA300 +,0x0260 +,0xA306 +,0x0262 +,0xFA52 +,0x4044 +,0x1609 +,0x41E6 +,0x0894 +,0x1406 +,0xB4F2 +,0x0001 +,0x0B07 +,0xBC20 +,0x01F9 +,0xA302 +,0x02A7 +,0xBC40 +,0x1C01 +,0xBC40 +,0x3401 +,0x144E +,0x24A1 +,0xBC24 +,0x029A +,0xBC40 +,0x140C +,0xBC21 +,0x0267 +,0xBC22 +,0x0294 +,0xBC3C +,0x4000 +,0x6D79 +,0x640E +,0xBC3F +,0x0285 +,0xBC3B +,0x0290 +,0xBC30 +,0x2000 +,0x7000 +,0x244F +,0xBC40 +,0x6607 +,0xA31F +,0x028F +,0xA31B +,0x0293 +,0xBC40 +,0x0C9C +,0xBC40 +,0x149C +,0xBC40 +,0x151E +,0xBC40 +,0x2C80 +,0xBC40 +,0x3490 +,0xBC40 +,0x3C9A +,0xBC40 +,0x2D10 +,0xBC40 +,0x1D03 +,0x40A7 +,0xBC02 +,0x05B3 +,0xB04A +,0x0318 +,0xBC23 +,0x30FD +,0xBC22 +,0x30FF +,0xA304 +,0x0325 +,0xFA74 +,0xFA52 +,0x04F2 +,0xBC21 +,0x02E0 +,0x3589 +,0xB00E +,0x0318 +,0xA306 +,0x0312 +,0xA300 +,0x0326 +,0xBC26 +,0x30FC +,0xBC20 +,0x3102 +,0xFAD6 +,0xFA10 +,0xA306 +,0x0360 +,0x14AA +,0x1428 +,0x14EB +,0xA304 +,0x035F +,0xBC26 +,0x2021 +,0x35CD +,0xBC25 +,0x0327 +,0xBC24 +,0x07C0 +,0xBC3E +,0x7FFF +,0xBC3A +,0x0320 +,0xB012 +,0x0019 +,0xB024 +,0xFFFF +,0xB000 +,0xFFFF +,0x6D4B +,0x3BD4 +,0xA305 +,0x0354 +,0xA31E +,0x047A +,0xA31A +,0x02DC +,0xA301 +,0x0314 +,0xA307 +,0x0313 +,0xA304 +,0x0353 +,0xA302 +,0x0363 +,0xA303 +,0x0364 +,0xA300 +,0x0365 +,0xBC02 +,0x0263 +,0xBC02 +,0x07A4 +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0x700F +,0xBA10 +,0x0801 +,0x2680 +,0x8F09 +,0xBC20 +,0x2040 +,0x7008 +,0x4FD5 +,0xFA10 +,0x0801 +,0x2600 +,0x8F10 +,0xA301 +,0x0099 +,0x8D0F +,0xBC20 +,0x2008 +,0xBC21 +,0xFF7F +,0x7007 +,0x3A12 +,0x6214 +,0x4FD5 +,0xA31C +,0x0099 +,0xA31C +,0x02A7 +,0xA31E +,0x008D +,0xFB11 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0474 +,0x6914 +,0x4FD5 +,0x4020 +,0xE9FE +,0xA309 +,0x008B +,0xA309 +,0x008C +,0xA300 +,0x00A0 +,0xBC00 +,0x0263 +,0xBC22 +,0x036A +,0xBC21 +,0x044C +,0x044A +,0x3509 +,0x32C0 +,0x4001 +,0x4023 +,0x8F01 +,0x8B04 +,0xE501 +,0x2680 +,0x8F02 +,0xBC22 +,0x2040 +,0x8E00 +,0xFB51 +,0xBC22 +,0x305A +,0x40BC +,0x703F +,0xBA52 +,0xBC3A +,0x0376 +,0xBC2E +,0x0399 +,0x4FEF +,0xBC28 +,0x03A8 +,0x2680 +,0x149A +,0x4270 +,0xA31E +,0x0372 +,0xA31A +,0x0375 +,0xA310 +,0x0395 +,0xA31C +,0x0396 +,0xA31C +,0x0397 +,0xA30E +,0x0398 +,0xA30F +,0x03B8 +,0xA308 +,0x03A6 +,0xA302 +,0x03A5 +,0xBC20 +,0x2040 +,0x8F01 +,0x4042 +,0xFB12 +,0xBC20 +,0x3079 +,0xBC3E +,0x03DC +,0xBC3A +,0x041A +,0xBC24 +,0x2044 +,0xFA03 +,0xBC30 +,0x03F1 +,0xA31E +,0x03DB +,0xA31A +,0x0442 +,0xA310 +,0x03F0 +,0xFB91 +,0xA301 +,0x03E2 +,0xA303 +,0x03E0 +,0xBC22 +,0x2043 +,0x8EC0 +,0xA300 +,0x03E1 +,0xFB51 +,0xE902 +,0xA200 +,0x008C +,0xA201 +,0x0082 +,0x6980 +,0x5FD5 +,0x8F16 +,0x2611 +,0x8F14 +,0x2612 +,0x8F11 +,0xBC20 +,0x201A +,0x4201 +,0xFA10 +,0x0801 +,0x2680 +,0x8F00 +,0xBC02 +,0x06A8 +,0xBC20 +,0x201F +,0xBC21 +,0x03FF +,0xFA10 +,0x0801 +,0xBC22 +,0x2002 +,0x8C06 +,0xFB50 +,0xBC20 +,0x2002 +,0xA201 +,0x0089 +,0xFB11 +,0xBC20 +,0x2000 +,0x4021 +,0xFB11 +,0xFA11 +,0x2693 +,0x8FFC +,0x8E00 +,0xBC20 +,0x2000 +,0x4001 +,0xBC22 +,0x2020 +,0x7010 +,0x3B11 +,0xFA51 +,0x0808 +,0x2600 +,0x4021 +,0x8F0C +,0xBC20 +,0x2001 +,0x8E00 +,0xFB11 +,0xFA11 +,0x2693 +,0x8FFC +,0x8E00 +,0x7000 +,0x4FD5 +,0xBC20 +,0x2001 +,0x8C02 +,0xFB11 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x201B +,0x4022 +,0xFA10 +,0x4381 +,0x0902 +,0x0841 +,0x4043 +,0x2640 +,0x0803 +,0x124B +,0xA204 +,0x0089 +,0xBC23 +,0x201D +,0x8F10 +,0x0461 +,0xFA73 +,0xA301 +,0x0089 +,0x218B +,0x8F1A +,0x2600 +,0xBC20 +,0x201C +,0x8F03 +,0xFA10 +,0x8C15 +,0xA300 +,0x0089 +,0xA302 +,0x0086 +,0x8D10 +,0xBC25 +,0x201C +,0x0061 +,0xFAB4 +,0xA301 +,0x0089 +,0x208C +,0x8F07 +,0x2600 +,0x8F03 +,0xFA70 +,0x8C04 +,0xA300 +,0x0089 +,0xA302 +,0x0086 +,0xBC20 +,0x201F +,0xBC21 +,0x03FF +,0xFA10 +,0xA203 +,0x0089 +,0x0801 +,0x2258 +,0x8F03 +,0x8EC0 +,0xA302 +,0x0086 +,0x8E00 +,0x8EB8 +,0xBC20 +,0x201B +,0x4381 +,0xFA10 +,0x0801 +,0xA201 +,0x0089 +,0xB480 +,0x0002 +,0xBC22 +,0x201C +,0x0008 +,0xFA51 +,0x2001 +,0xA300 +,0x0089 +,0x8F03 +,0x8EC0 +,0x4020 +,0xA300 +,0x0086 +,0x8EB8 +,0xE902 +,0xBC22 +,0x2000 +,0xDFD5 +,0x41A3 +,0xBC02 +,0x0723 +,0x4344 +,0xBC25 +,0x0400 +,0x2620 +,0x8F05 +,0xBC02 +,0x07F0 +,0x5404 +,0x4025 +,0xBC02 +,0x07F0 +,0x8D06 +,0xBC02 +,0x07FB +,0x5404 +,0x4025 +,0xBC02 +,0x07FB +,0xBC02 +,0x072A +,0x4E20 +,0xBC02 +,0x07B8 +,0xBC20 +,0x0001 +,0x0848 +,0xB412 +,0x0000 +,0xBC22 +,0x1000 +,0x4183 +,0xBC02 +,0x0723 +,0x220A +,0x8F3F +,0xDFE2 +,0xBC21 +,0x2098 +,0x41C2 +,0xFA33 +,0x0ADA +,0xFB33 +,0x4060 +,0x4841 +,0xBC02 +,0x07D8 +,0xBC21 +,0x2098 +,0x4202 +,0xBC20 +,0xFFFE +,0x0ADA +,0xFB33 +,0x08D8 +,0xFB33 +,0x4E20 +,0xBC02 +,0x07B8 +,0xBC22 +,0xFFFE +,0x084A +,0xCFE2 +,0x0A4A +,0xBC02 +,0x07CA +,0x4224 +,0xBC25 +,0x4000 +,0xBC02 +,0x07FB +,0x4044 +,0x4045 +,0xBC02 +,0x07FB +,0x4284 +,0x4105 +,0xBC02 +,0x07FB +,0x4284 +,0x4105 +,0xBC02 +,0x07F0 +,0xCFE0 +,0xBC02 +,0x0733 +,0x4E24 +,0x4045 +,0xBC02 +,0x07FB +,0x4E24 +,0x4045 +,0xBC02 +,0x07F0 +,0xBC20 +,0x2098 +,0x43E1 +,0xFB11 +,0x4021 +,0xFB11 +,0xBC22 +,0x4000 +,0x41C3 +,0xBC02 +,0x0723 +,0x38A2 +,0x4E20 +,0xBC02 +,0x07B8 +,0xB55A +,0x0002 +,0x0A4D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC20 +,0x201F +,0x8E00 +,0xFA10 +,0x0890 +,0x1093 +,0x8EB8 +,0xE902 +,0x4E24 +,0xDFD5 +,0x4085 +,0xBC02 +,0x07FB +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0xBC21 +,0x202D +,0xDFD5 +,0xDFE0 +,0x4280 +,0xBC02 +,0x07CA +,0xBC22 +,0x8018 +,0xBC23 +,0x8098 +,0xCFE0 +,0x2600 +,0x1853 +,0x42C0 +,0xBC02 +,0x07CA +,0x4240 +,0xBC21 +,0xE419 +,0xBC02 +,0x07CA +,0x4260 +,0xBC21 +,0x9010 +,0xBC02 +,0x07CA +,0x4040 +,0xBC21 +,0x0FFB +,0xBC02 +,0x07CA +,0x4220 +,0xBC21 +,0x2020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07D8 +,0x4220 +,0xBC21 +,0x1020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07D8 +,0x4220 +,0xBC21 +,0x4020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07D8 +,0x4520 +,0xBC21 +,0x8001 +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0xBC20 +,0x2023 +,0xDFD5 +,0xFA16 +,0xBC20 +,0x2000 +,0x09B0 +,0xDFE6 +,0x4060 +,0xBC02 +,0x07B8 +,0xBC22 +,0x39AE +,0xBC23 +,0x19AE +,0xCFE6 +,0x2660 +,0x195A +,0x220D +,0x8F02 +,0x3825 +,0xBC02 +,0x07CA +,0x4480 +,0xBC02 +,0x07B8 +,0xBC22 +,0x0000 +,0xBC23 +,0x0001 +,0xCFE6 +,0x2660 +,0x195A +,0x220D +,0x8F02 +,0x3825 +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0x4E04 +,0x4805 +,0xDFD5 +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0xFA10 +,0x0801 +,0x2600 +,0x8F01 +,0xBC02 +,0x07FB +,0x8D02 +,0xBC02 +,0x07F0 +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC22 +,0x209A +,0xBC23 +,0x0100 +,0x0AD8 +,0xBC21 +,0x209D +,0xFB53 +,0x4043 +,0xFA32 +,0x0893 +,0x26A0 +,0x8FFA +,0xBC22 +,0x209C +,0x8E00 +,0xFA51 +,0x8EB8 +,0xBC22 +,0x209A +,0xBC23 +,0x209B +,0xFB50 +,0xBC22 +,0x209D +,0xFB71 +,0x4023 +,0xFA51 +,0x084B +,0x2690 +,0x8FFB +,0x8EB8 +,0xBC08 +,0x07E6 +,0x8E00 +,0xBDC8 +,0x07E5 +,0x8E00 +,0xBC09 +,0x07E4 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8EB8 +,0xBC08 +,0x07EE +,0x8E00 +,0xBC09 +,0x07ED +,0x8E00 +,0x8E00 +,0x8EB8 +,0xE902 +,0x3804 +,0xDFD5 +,0xBC02 +,0x07B8 +,0x0A4D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0x1745 +,0xDFD5 +,0x3804 +,0xBC02 +,0x07B8 +,0x084D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC20 +,0x201A +,0x4201 +,0xFA10 +,0x0801 +,0x2600 +,0x8F00 +,0x8EB8 +,0xE902 +,0x4020 +,0xDFD5 +,0xBC21 +,0x1F2A +,0xBC02 +,0x07CA +,0xBC20 +,0x01F4 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x402D +,0xBC02 +,0x07CA +,0x4280 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x5FED +,0xBC02 +,0x07CA +,0x4020 +,0xBC21 +,0x1F6A +,0xBC02 +,0x07CA +,0x4280 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x7FED +,0xBC02 +,0x07CA +,0x4500 +,0x4461 +,0xBC02 +,0x07E8 +,0xBC20 +,0x2023 +,0xBC22 +,0x39AE +,0xBC23 +,0x19AE +,0xFA10 +,0xBC21 +,0x2000 +,0x0841 +,0x38C1 +,0x2610 +,0x185A +,0x4060 +,0xBC02 +,0x07CA +,0x4040 +,0xBC21 +,0x0FF9 +,0xBC02 +,0x07CA +,0xBC20 +,0x000A +,0x4461 +,0xBC02 +,0x07E8 +,0x4022 +,0x4003 +,0x2660 +,0x1853 +,0x4480 +,0xBC02 +,0x07CA +,0x4540 +,0xBC02 +,0x07B8 +,0xDFE1 +,0x40C0 +,0x4202 +,0x41E3 +,0x4104 +,0xBC25 +,0x31EC +,0x41E6 +,0xBC02 +,0x08EC +,0x41C0 +,0xBC24 +,0x87FF +,0x4166 +,0xBC02 +,0x08F9 +,0xCFE1 +,0x4000 +,0x4402 +,0x43E3 +,0x4164 +,0xBC25 +,0x31ED +,0x43E6 +,0xBC02 +,0x08EC +,0xDFE5 +,0x4180 +,0xBC24 +,0xFF07 +,0x4066 +,0xBC02 +,0x08F9 +,0xCFE5 +,0x40E0 +,0xBC24 +,0xFFE0 +,0x4006 +,0xBC02 +,0x08F9 +,0x4000 +,0xBC02 +,0x0733 +,0xBC20 +,0x2098 +,0x43E1 +,0xFB11 +,0x4021 +,0xFB11 +,0x4500 +,0x4401 +,0xBC02 +,0x07CA +,0x4140 +,0xBC21 +,0x0841 +,0xBC02 +,0x07CA +,0xBC20 +,0x01F4 +,0x4841 +,0xBC02 +,0x07E8 +,0x4140 +,0xBC21 +,0x0840 +,0xBC02 +,0x07CA +,0x4500 +,0x4001 +,0xBC02 +,0x07CA +,0xBC21 +,0x2023 +,0xBC22 +,0x0400 +,0xFA31 +,0x084A +,0x2610 +,0x8F0A +,0x5364 +,0x4065 +,0xBC02 +,0x07F0 +,0x4AC0 +,0x4021 +,0xBC02 +,0x07CA +,0xBC21 +,0x1FFA +,0x8D02 +,0xBC21 +,0x1FFB +,0x4040 +,0xBC02 +,0x07CA +,0x4C80 +,0x4841 +,0xBC02 +,0x07E8 +,0x41E0 +,0xBC21 +,0x4042 +,0xBC02 +,0x07CA +,0xBC02 +,0x07A4 +,0x4E80 +,0x4021 +,0xBC02 +,0x07CA +,0x4E60 +,0xBC21 +,0x0480 +,0xBC02 +,0x07CA +,0x5380 +,0xBC21 +,0xAB40 +,0xBC02 +,0x07CA +,0x4102 +,0x4503 +,0xBC24 +,0x2023 +,0xBC25 +,0x0400 +,0xFA94 +,0x0925 +,0x2640 +,0x1853 +,0x53C0 +,0xBC02 +,0x07CA +,0x4E04 +,0x4025 +,0xBC02 +,0x07FB +,0xCFD5 +,0xE9FE +,0x8EB8 +,0x1048 +,0x0891 +,0x08D9 +,0x2620 +,0x1863 +,0xFAB2 +,0x004A +,0x4002 +,0x3210 +,0x1851 +,0x210E +,0x1971 +,0x8EB8 +,0xE901 +,0x8E00 +,0xDFF5 +,0xBC02 +,0x07B8 +,0x0861 +,0x316E +,0x0A4D +,0xBC02 +,0x07CA +,0xCFF5 +,0xE9FF +,0x8EB8 +,0xBC20 +,0x209F +,0xBC21 +,0x31DB +,0xA300 +,0x047E +,0xA301 +,0x047D +,0xBD11 +,0x0911 +,0xFA22 +,0xFB02 +,0x8EC0 +,0xA300 +,0x047E +,0xA301 +,0x047D +,0x0000 +,0x6915 +,0xA908 +,0xA21B +,0x0180 +,0xA21E +,0x017E +,0xA21D +,0x016E +,0xBC3C +,0x3116 +,0xBC30 +,0x311D +,0x7016 +,0xDF1B +,0xA204 +,0x017F +,0xA202 +,0x0181 +,0xA203 +,0x0182 +,0xA201 +,0x01AD +,0x6915 +,0x1F3D +,0x77F6 +,0x9F5E +,0xBC26 +,0x3106 +,0xDF70 +,0xDF9C +,0xBD08 +,0x09DB +,0xA200 +,0x015E +,0xBC3C +,0x009C +,0xBC3E +,0x00C2 +,0xA304 +,0x017F +,0x6E7B +,0x9FA1 +,0x6E43 +,0xBAC5 +,0x6E4B +,0xBE18 +,0x396C +,0x8A0E +,0xBF95 +,0x8A18 +,0x77E6 +,0x9FC6 +,0x6A91 +,0x7AD5 +,0x7077 +,0xFE18 +,0x6A91 +,0x4F86 +,0x88D0 +,0x6E62 +,0xFAC7 +,0x6E7A +,0x5FE0 +,0x39C8 +,0x8890 +,0xBC3D +,0x0170 +,0x6FCA +,0x4F41 +,0x6910 +,0xBAC5 +,0x6910 +,0xFF38 +,0x7016 +,0xBE38 +,0x2A47 +,0x6A91 +,0xFE38 +,0xBF95 +,0x8A38 +,0x6A91 +,0x7AC7 +,0xBF95 +,0x8A38 +,0xBF9D +,0x8E38 +,0xBF95 +,0xAA38 +,0x2A47 +,0x6A91 +,0xFE38 +,0x2A45 +,0x88D0 +,0x398B +,0x39E9 +,0x39C8 +,0x88F0 +,0xB06C +,0xFFFA +,0x613E +,0xDF86 +,0xBC26 +,0x7ADD +,0xBCB7 +,0x8000 +,0x04AA +,0xBC26 +,0x7ADD +,0xBCA5 +,0x8000 +,0xA300 +,0x015E +,0x6025 +,0x0F00 +,0x6FCB +,0xCFC4 +,0x6036 +,0x0FE0 +,0xB048 +,0xFFF1 +,0x6910 +,0xBF38 +,0x6910 +,0xDF41 +,0xFA86 +,0x6960 +,0x3E18 +,0x8A0E +,0xBF99 +,0x0C18 +,0x7076 +,0x9F07 +,0x6A91 +,0xBA96 +,0x7016 +,0xBE18 +,0x2A46 +,0x88E0 +,0x398B +,0x39E9 +,0x39C8 +,0x88F0 +,0xA300 +,0x015E +,0x7077 +,0x8F20 +,0xBC3C +,0x0160 +,0x6FCD +,0xCF66 +,0x6910 +,0xBF18 +,0x6910 +,0xFAC7 +,0x7147 +,0xFE18 +,0x2A47 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0x2A47 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0x2A47 +,0xBF9D +,0xAE18 +,0x2A47 +,0x88F0 +,0xB06C +,0xFFFA +,0x6E62 +,0xDF66 +,0x39E9 +,0x39C8 +,0x88E0 +,0x0E7A +,0x3F3E +,0x63EC +,0xFF18 +,0x6FC3 +,0x8FA1 +,0xBC3D +,0x0184 +,0xB068 +,0xFFF1 +,0x6915 +,0xBF38 +,0x6915 +,0x1F20 +,0x5FDA +,0x3885 +,0xCF1E +,0xCF50 +,0xA310 +,0x017E +,0xA301 +,0x01AD +,0xA304 +,0x017F +,0xA302 +,0x0181 +,0xA31E +,0x0180 +,0xA303 +,0x0182 +,0xCF3B +,0x8EC0 +,0xE9F8 +,0xA31B +,0x016E +,0x0000 +,0x2451 +,0xA201 +,0x01AC +,0x3909 +,0xBC22 +,0x3124 +,0x2453 +,0xBC3D +,0x0184 +,0x451F +,0xBD08 +,0x0A11 +,0x77F6 +,0xFA43 +,0x2442 +,0x6960 +,0x3E38 +,0x8A0C +,0xBF8C +,0x8638 +,0x2A43 +,0x88B0 +,0x398B +,0x39E9 +,0x39C8 +,0x88C0 +,0x439B +,0x6E18 +,0x2403 +,0xB024 +,0xFFF3 +,0x6D06 +,0xA444 +,0x6910 +,0xEA38 +,0x8EC0 +,0xA301 +,0x01AC +,0x8E00 +,0xBC20 +,0x3131 +,0xA201 +,0x02C2 +,0xFA10 +,0x2600 +,0x8F3E +,0xA200 +,0x01E2 +,0x2680 +,0x8F39 +,0x2610 +,0xA200 +,0x01BE +,0xB010 +,0xFFFF +,0x8F2C +,0xA202 +,0x01E3 +,0x26A0 +,0x8F28 +,0xBC22 +,0x02A8 +,0xBC23 +,0x3133 +,0xBC24 +,0x3132 +,0xBC40 +,0x3906 +,0xFA73 +,0xBC25 +,0x3134 +,0xBC27 +,0x3135 +,0xBC40 +,0x3102 +,0xFA94 +,0x04F3 +,0xFAB5 +,0xFAF6 +,0x04A2 +,0x1095 +,0x10DE +,0x1D1A +,0x4003 +,0x3240 +,0x3843 +,0x8F02 +,0xB228 +,0x0040 +,0x4803 +,0x18DC +,0x2103 +,0x8F05 +,0x2183 +,0x8F18 +,0x3401 +,0xA300 +,0x01BE +,0x8D15 +,0x8C14 +,0xA301 +,0x01BE +,0x3280 +,0x4002 +,0x8F0D +,0xA301 +,0x01BE +,0x8D0C +,0x8C0B +,0x4002 +,0x2690 +,0x4800 +,0x4002 +,0x8F03 +,0x8E00 +,0x8C04 +,0xA302 +,0x01BE +,0xA300 +,0x01BE +,0xA200 +,0x01BE +,0x2600 +,0xBC21 +,0x2035 +,0x4020 +,0x8EC0 +,0x1810 +,0xFB30 +,0x0000 +,0x38E0 +,0xA200 +,0x01E1 +,0xB202 +,0x0040 +,0x405A +,0xBC3C +,0x01C0 +,0x441E +,0x8F0F +,0x6E11 +,0xE800 +,0xBD08 +,0x0A88 +,0x6D74 +,0xA103 +,0xE142 +,0x1B1A +,0x0E9A +,0x3F14 +,0x6E11 +,0xFF18 +,0x8E00 +,0x8EC0 +,0xA300 +,0x01E1 +,0x8E00 +,0xB522 +,0x0009 +,0x3867 +,0xBD08 +,0x0A9D +,0x6D76 +,0xA184 +,0xE1C3 +,0xBCB6 +,0x8000 +,0x8E00 +,0x1B63 +,0x0EE3 +,0x3F1D +,0x6E19 +,0xFF18 +,0x8E00 +,0x8EC0 +,0xA300 +,0x01E1 +,0x8E00 +,0xA200 +,0x01F7 +,0x2600 +,0xA200 +,0x01E4 +,0x8F44 +,0xA201 +,0x01F8 +,0x2690 +,0x8F41 +,0xBC21 +,0x3173 +,0xA202 +,0x01E5 +,0xFA31 +,0x2191 +,0x8F02 +,0x3491 +,0xA302 +,0x01E5 +,0xA202 +,0x01E5 +,0x2251 +,0x8F33 +,0xBC21 +,0x02A8 +,0xBC23 +,0x316F +,0xBC25 +,0x316C +,0xBC40 +,0x4086 +,0xFA73 +,0xBC22 +,0x316D +,0xBC24 +,0x316E +,0x680C +,0xFAB3 +,0xFA52 +,0xFA94 +,0x38A3 +,0x8F04 +,0xBC23 +,0x3170 +,0x8E00 +,0xFA73 +,0x2033 +,0x18D4 +,0xBC26 +,0x3171 +,0xBC40 +,0x4881 +,0xFAD6 +,0x210E +,0x8F04 +,0xBC25 +,0x3172 +,0x8E00 +,0xFAB5 +,0x210D +,0x1954 +,0x1E5D +,0x2208 +,0x401E +,0x8F0A +,0x2108 +,0xA31E +,0x01E5 +,0x8F03 +,0x8E00 +,0x8C05 +,0xB000 +,0xFFFF +,0x3401 +,0x8D01 +,0x4000 +,0x40A1 +,0x2801 +,0xA300 +,0x01E4 +,0x382E +,0xB012 +,0x3136 +,0xBC20 +,0x3163 +,0xBD04 +,0x0AFB +,0xFA22 +,0xFB02 +,0xFA2A +,0xFB02 +,0xBD04 +,0x0B01 +,0xFA2A +,0xFB02 +,0x8EB8 +,0x0000 +,0x2451 +,0xA201 +,0x01E0 +,0x3909 +,0xBC22 +,0x3163 +,0x2453 +,0xBC3D +,0x01C0 +,0x441F +,0xBD08 +,0x0B25 +,0x77F6 +,0xFA43 +,0x2442 +,0x6960 +,0x3E38 +,0x8A08 +,0xBF8C +,0x8638 +,0x2A43 +,0x88B0 +,0x398B +,0x39E9 +,0x39C8 +,0x88C0 +,0x429B +,0x6E18 +,0x2403 +,0xB024 +,0xFFF7 +,0x6D06 +,0xA444 +,0x6910 +,0xEA38 +,0x8EC0 +,0xA301 +,0x01E0 +,0x8E00 +,0xBC20 +,0x31B2 +,0x5FE1 +,0xFA10 +,0xB020 +,0x319C +,0xB012 +,0x319C +,0x0008 +,0xBC23 +,0x01F9 +,0xFA10 +,0xBC40 +,0x1981 +,0x6862 +,0x3A52 +,0xBC40 +,0x3582 +,0x8F06 +,0xA200 +,0x0085 +,0x2681 +,0x8F03 +,0x8EC0 +,0x4040 +,0xA300 +,0x0085 +,0x8EB8 +,0x0000 +,0xBC21 +,0x02A8 +,0xBC23 +,0x0263 +,0xBC40 +,0x4880 +,0xBC40 +,0x5084 +,0x6E10 +,0xE580 +,0x7000 +,0x25C4 +,0xA203 +,0x0266 +,0xBC40 +,0x5881 +,0x2630 +,0xBC40 +,0x1501 +,0x401C +,0x8F28 +,0x3820 +,0xB532 +,0x0002 +,0xB036 +,0x3174 +,0x3882 +,0x6910 +,0xBA65 +,0x6960 +,0x2206 +,0x8A02 +,0xBBD4 +,0xCA86 +,0x6A3D +,0x7A73 +,0x88C0 +,0x3215 +,0x00E3 +,0x8F05 +,0xB416 +,0x0002 +,0x0441 +,0x3214 +,0x1801 +,0x8C0A +,0x3B80 +,0x3330 +,0x8F04 +,0x2614 +,0x8F04 +,0x8E00 +,0x8CE1 +,0x3449 +,0x344D +,0x8DDE +,0xBC20 +,0x31B2 +,0x383C +,0xFA10 +,0x2108 +,0x1801 +,0xB000 +,0x319C +,0x8EC0 +,0xFA10 +,0xA300 +,0x01FF +,0xBC25 +,0x01F9 +,0x34AB +,0xE904 +,0xE143 +,0x6122 +,0xDF82 +,0x3320 +,0x8F02 +,0xBC23 +,0x31B4 +,0x8C05 +,0xFA73 +,0xBC23 +,0x31B3 +,0x8E00 +,0xFA73 +,0x2813 +,0xA201 +,0x0260 +,0xBC40 +,0x268E +,0xBC40 +,0x2E8F +,0x6D4A +,0xA29E +,0x700E +,0xE2DC +,0x7307 +,0xDFDE +,0x6E7F +,0x224C +,0xCFCE +,0x6A34 +,0xDFA5 +,0x6E28 +,0x2800 +,0xBC3D +,0x0200 +,0x6EE3 +,0xE287 +,0x88E0 +,0xBD07 +,0x0BC7 +,0x6D00 +,0x9FCE +,0xBCFF +,0x8000 +,0x8E00 +,0xE4E7 +,0xE2C5 +,0xBCDB +,0x8000 +,0x6E7F +,0x0FCE +,0x6A34 +,0xE4E5 +,0x38A0 +,0x88E0 +,0x6EE3 +,0xE287 +,0xDFCE +,0xBCFF +,0x8000 +,0xCF82 +,0xE4E7 +,0xE2C5 +,0xBCDB +,0x8000 +,0xE64C +,0xE4E5 +,0xCFDF +,0xE546 +,0xA301 +,0x0260 +,0xA31F +,0x01F9 +,0xCFA3 +,0x8EC0 +,0xE9FC +,0xE5DC +,0x0000 +,0xBC22 +,0x31B7 +,0x8E00 +,0xFA52 +,0x26A0 +,0x8F04 +,0x8EC0 +,0xBC22 +,0x6568 +,0xA302 +,0x0268 +,0xA200 +,0x0261 +,0x403A +,0xBC3C +,0x0200 +,0x4C1E +,0x8E00 +,0xE062 +,0xA300 +,0x0261 +,0x6904 +,0xBC1B +,0x241B +,0xBD1E +,0x0BFA +,0x67A6 +,0xBC1B +,0x241B +,0x1E9A +,0xBC3D +,0x0290 +,0xA201 +,0x0293 +,0x3B7A +,0x407F +,0xBC23 +,0x31B6 +,0x6EE7 +,0x64E2 +,0xFA73 +,0xA204 +,0x02B0 +,0xA300 +,0x0261 +,0xA301 +,0x0293 +,0x21A3 +,0x8F2C +,0xA200 +,0x0293 +,0x407E +,0xBC23 +,0x31B5 +,0x7016 +,0xBC1C +,0x1EA2 +,0xB800 +,0xE61C +,0x1EA2 +,0x1E93 +,0xB124 +,0x0001 +,0xBC23 +,0x2000 +,0xBCA4 +,0xC000 +,0xBC24 +,0x3FFF +,0x24DA +,0xB056 +,0xFFFF +,0x3095 +,0x0562 +,0xA300 +,0x0293 +,0x4004 +,0xBD0B +,0x0C39 +,0x33D0 +,0xB56A +,0x0001 +,0x8F02 +,0xB548 +,0x0001 +,0x8C05 +,0x0172 +,0x3521 +,0x0572 +,0xB548 +,0x0001 +,0x8E00 +,0x30A3 +,0xA302 +,0x0269 +,0xA202 +,0x0269 +,0xA203 +,0x0268 +,0x0493 +,0x3220 +,0xBC23 +,0x0400 +,0x8F02 +,0xBC23 +,0x31B8 +,0x8E00 +,0xFA73 +,0xBC24 +,0x0267 +,0x281A +,0xE643 +,0x8EC0 +,0xBC40 +,0x260F +,0xBC40 +,0x1E0E +,0x0000 +,0xBC23 +,0x0267 +,0x349D +,0xE904 +,0x6D57 +,0xA15F +,0x6D27 +,0xDF82 +,0x700E +,0xA2DD +,0xBC40 +,0x2184 +,0x6E7F +,0x5FDF +,0xBC40 +,0x1983 +,0x7307 +,0xA14C +,0xCFCE +,0x6AA7 +,0x1FA5 +,0xA200 +,0x0262 +,0xBC3C +,0x0200 +,0x88E0 +,0x6EEB +,0xFC1F +,0x6960 +,0x1FCE +,0xBC25 +,0x026F +,0xBCFD +,0xC000 +,0xBD07 +,0x0C8C +,0xB51E +,0x0002 +,0x6D7A +,0xA681 +,0xE061 +,0xBC9C +,0x4000 +,0x6E7F +,0x4FCE +,0xB512 +,0x0002 +,0x6AA7 +,0x26C1 +,0x88E0 +,0x6E29 +,0xDFCE +,0x6EEB +,0xFC1F +,0xBCFD +,0xC000 +,0x8E00 +,0xB51E +,0x0002 +,0xE681 +,0xE061 +,0xBC9C +,0x4000 +,0xCFA3 +,0xB512 +,0x0002 +,0xBC24 +,0x0267 +,0xE6C1 +,0xE5DD +,0xE54C +,0xA300 +,0x0262 +,0xBC40 +,0x0E06 +,0xCF85 +,0xCFDE +,0x8EC0 +,0xE9FC +,0xE6DE +,0xA200 +,0x02A7 +,0x2600 +,0xBC01 +,0x0D4B +,0xA203 +,0x0294 +,0x2630 +,0xA202 +,0x02C5 +,0xBC25 +,0x1000 +,0xA200 +,0x02C6 +,0xA204 +,0x02C3 +,0xA201 +,0x01BE +,0xBCA5 +,0x4000 +,0xBC23 +,0x0294 +,0x8F33 +,0xBC26 +,0x31CE +,0xBC40 +,0x1185 +,0x6990 +,0x7AD4 +,0x0495 +,0xBCA5 +,0x0000 +,0xBC26 +,0x31CF +,0x00AA +,0xBC25 +,0x31D0 +,0xBC40 +,0x1984 +,0xBC40 +,0x2187 +,0x0404 +,0xFAD6 +,0x044F +,0xFAB5 +,0xBC81 +,0x8000 +,0xBC93 +,0x4000 +,0x0020 +,0x0079 +,0xA204 +,0x0299 +,0xBC40 +,0x1582 +,0xBC40 +,0x1D80 +,0xBC40 +,0x2581 +,0x8F07 +,0x32C0 +,0x4000 +,0x8F00 +,0xB008 +,0xFFFF +,0x8C13 +,0xA300 +,0x0299 +,0xBC20 +,0x4000 +,0x21A0 +,0x8F00 +,0x3421 +,0x8C0B +,0xA300 +,0x0299 +,0x403E +,0xBC40 +,0x1D80 +,0xA31E +,0x0294 +,0xBC40 +,0x2581 +,0xBC40 +,0x1582 +,0xBC20 +,0x31D1 +,0xBC40 +,0x1185 +,0xFA10 +,0x20A8 +,0x4020 +,0xBC40 +,0x1981 +,0x3840 +,0x8F06 +,0xBC20 +,0x31D2 +,0x8E00 +,0xFA10 +,0x2088 +,0x3802 +,0x8F00 +,0x4000 +,0xBC24 +,0x31D3 +,0xBC40 +,0x2183 +,0xFA94 +,0xBC27 +,0x31EE +,0x4006 +,0x6867 +,0x3AF3 +,0x1932 +,0x202B +,0x8F04 +,0xBC23 +,0x31EF +,0x8E00 +,0xFA73 +,0x218B +,0x8F00 +,0x3886 +,0x2640 +,0xBC21 +,0x029A +,0x8F0B +,0xBC23 +,0x31D4 +,0xA204 +,0x0299 +,0xFA73 +,0x2023 +,0x8F01 +,0x2600 +,0x8F03 +,0x8E00 +,0x8C13 +,0xA306 +,0x0295 +,0xBC20 +,0x31F7 +,0xBC40 +,0x2083 +,0xFA10 +,0x2118 +,0x1803 +,0xA302 +,0x0295 +,0xBC40 +,0x1C86 +,0xBC40 +,0x1486 +,0xBC40 +,0x5C86 +,0xBC40 +,0x2480 +,0xBC40 +,0x2080 +,0xB230 +,0x7530 +,0x4C02 +,0x8EC0 +,0x1810 +,0xBC40 +,0x2480 +,0x8EC0 +,0x4000 +,0xA300 +,0x0294 +,0x0000 +,0xBC22 +,0x31F0 +,0xE91C +,0xBC24 +,0x029A +,0x7007 +,0x3A52 +,0x6E11 +,0x1C82 +,0x6E7F +,0x3C85 +,0xBC26 +,0x31F4 +,0xBC23 +,0x31F3 +,0x77FE +,0xDCA4 +,0xBC27 +,0x31F2 +,0xB801 +,0xA891 +,0x7027 +,0xFA73 +,0xFAF6 +,0xDCC3 +,0xBC27 +,0x31D5 +,0xBC23 +,0x31DA +,0xDD26 +,0xDD04 +,0xFAF6 +,0xBC24 +,0x31F5 +,0xFA73 +,0xDD66 +,0xDD43 +,0xFA96 +,0xB074 +,0x000B +,0xBC23 +,0x31D8 +,0xDDA6 +,0xDD87 +,0xBC26 +,0x31D7 +,0xB800 +,0xE6F7 +,0xDCE1 +,0xBC24 +,0x31D6 +,0x6D34 +,0x9DC3 +,0xDDE7 +,0xBC21 +,0x8000 +,0xFAD6 +,0xBC27 +,0x31D9 +,0xFA94 +,0x6163 +,0x9E46 +,0xE1DE +,0x6D34 +,0xDE03 +,0x6143 +,0x1E24 +,0xDE86 +,0xDE63 +,0xB801 +,0xEE73 +,0xB064 +,0x000C +,0xBC21 +,0x31F6 +,0xDEA7 +,0xDEE3 +,0xDF06 +,0xBC27 +,0x31F1 +,0xB034 +,0x0009 +,0x6D45 +,0x1EC4 +,0xB800 +,0x6CD1 +,0x6E81 +,0xBAF6 +,0xB024 +,0x000A +,0xDFA6 +,0xDF42 +,0xDF23 +,0xE1C3 +,0xE142 +,0xE246 +,0xDF64 +,0xDF8F +,0xBC3D +,0x029F +,0xBD08 +,0x0E56 +,0x6CD8 +,0x1FC1 +,0x7003 +,0x0E27 +,0x6915 +,0xA044 +,0x8F01 +,0x2640 +,0x8F6F +,0x6A3B +,0xCCE5 +,0x6D6C +,0x4EC7 +,0x6A3B +,0xDFE6 +,0x88D0 +,0xB20C +,0x0060 +,0xDCE5 +,0xCDC5 +,0x8F65 +,0x6A09 +,0x4D65 +,0x88FC +,0x6910 +,0x8C86 +,0x28DD +,0x28FD +,0x8890 +,0xBCFF +,0xC000 +,0xBC92 +,0x4000 +,0x2442 +,0x28D5 +,0x6A3F +,0x4CE5 +,0x88F0 +,0x686B +,0x8D26 +,0x611E +,0x4DE7 +,0x2409 +,0x8F05 +,0xCFA6 +,0x686B +,0x8CC5 +,0xCD06 +,0x666B +,0x8CE5 +,0x6113 +,0x5DFC +,0x2409 +,0x32F0 +,0xBCEC +,0x4000 +,0x8F05 +,0xCD41 +,0x686E +,0x5DFC +,0x8F01 +,0x35F9 +,0xDDE7 +,0x686D +,0x4EE6 +,0x401F +,0x8F12 +,0x6CB8 +,0x0DC5 +,0x3BBC +,0x8F09 +,0x38FE +,0xBC21 +,0x2666 +,0xBCFE +,0x4000 +,0xB06C +,0xFFFF +,0x3BA6 +,0x3BE7 +,0x0F27 +,0x6EF7 +,0xDEFD +,0xBC3D +,0x029F +,0x8C26 +,0x409F +,0xCDE5 +,0x69B4 +,0x0EA6 +,0x8F01 +,0x3569 +,0xDDE5 +,0x684B +,0x9EFC +,0x7027 +,0xCDC5 +,0xBC3D +,0x029F +,0x8F16 +,0x6910 +,0x8FC1 +,0x5BE5 +,0x28E5 +,0xBC25 +,0x31CA +,0x403B +,0xFAA6 +,0xE0E7 +,0x8A03 +,0xBBF9 +,0x4C3F +,0x6A3F +,0x9EF0 +,0x88D0 +,0x77FE +,0xDFC1 +,0x66EB +,0x0DC5 +,0x0F26 +,0x3BC6 +,0x8D02 +,0xDFE6 +,0xCDC5 +,0x6A09 +,0x4E47 +,0x88EC +,0x6915 +,0x0F8F +,0x6915 +,0x8E85 +,0x28F7 +,0x28DD +,0x88B0 +,0xBC9D +,0x8000 +,0xBCE6 +,0xC000 +,0x6915 +,0x0F8F +,0x2456 +,0x6A33 +,0xCFC1 +,0x28D5 +,0x88A0 +,0x8E00 +,0x0556 +,0x242D +,0x26D0 +,0x8F04 +,0xCFE6 +,0xCDA7 +,0x2137 +,0x19BE +,0xDFE6 +,0x6D00 +,0xA444 +,0x6915 +,0xEA38 +,0xE4C4 +,0xCFE6 +,0xCF44 +,0xCF27 +,0xCF00 +,0xE7C3 +,0xE642 +,0xA305 +,0x029A +,0xCE02 +,0xCD83 +,0xCF65 +,0xE441 +,0xCDE7 +,0xCE64 +,0xCEFB +,0xCCF0 +,0xCCA1 +,0xE9E4 +,0xE6C6 +,0xE5C7 +,0xE55E +,0x8EC0 +,0xE65B +,0xE4D0 +,0xBC21 +,0x02A8 +,0xE90E +,0x6E18 +,0x7C22 +,0xA204 +,0x02C4 +,0x6C28 +,0xA0C5 +,0xA200 +,0x02C2 +,0x6C49 +,0x5F04 +,0xB050 +,0x31BD +,0x6E0D +,0x1F55 +,0x6980 +,0x3AB6 +,0xB012 +,0xFFF2 +,0xA21E +,0x02C6 +,0xB000 +,0x31BF +,0x616C +,0xA4DE +,0x7000 +,0x5F21 +,0xFA12 +,0x4025 +,0x180D +,0x0554 +,0xB020 +,0x31BB +,0xA204 +,0x02C5 +,0xBC40 +,0x2187 +,0x31E7 +,0xFA52 +,0x0497 +,0xB000 +,0x31B9 +,0xBC40 +,0x1987 +,0x3127 +,0x6C88 +,0x3A10 +,0x0504 +,0x38F4 +,0xB00E +,0xFFF7 +,0x6622 +,0x9F60 +,0x6D37 +,0x6446 +,0xB06E +,0xFFF6 +,0x6C90 +,0x1F86 +,0x6643 +,0x2745 +,0xB05E +,0xFFF5 +,0xB07E +,0xFFF4 +,0xE1C6 +,0x6998 +,0x66C4 +,0xE7C2 +,0xDFC7 +,0xDFA5 +,0x8F54 +,0xBC20 +,0x02A8 +,0x700F +,0x8E44 +,0x65E3 +,0x0EC5 +,0xB5A8 +,0x000F +,0x65B3 +,0x65DE +,0xBC40 +,0xBC02 +,0xBC40 +,0x5404 +,0xB4AA +,0x0001 +,0xB5B6 +,0x000F +,0xB4C8 +,0x0001 +,0xB5EC +,0x000F +,0x62B6 +,0x8EA2 +,0x0BB4 +,0x170A +,0xBC40 +,0xC406 +,0xB4E4 +,0x0001 +,0xB5C8 +,0x000F +,0xBC40 +,0x9403 +,0x62C9 +,0x8E83 +,0x178B +,0xB4F6 +,0x0001 +,0xB5EC +,0x000F +,0x0BB7 +,0xBC40 +,0x8404 +,0xCEE4 +,0xB5FA +,0x000F +,0xBC40 +,0x4405 +,0x174C +,0xBC40 +,0x8C07 +,0xB4F8 +,0x0001 +,0xB5DA +,0x000F +,0xBC40 +,0x3C02 +,0xBC40 +,0x4C03 +,0xB5A4 +,0x000F +,0xB5B6 +,0x000F +,0xBC40 +,0x3404 +,0x0B6F +,0xB5C8 +,0x000F +,0xBC40 +,0x7C02 +,0xBC40 +,0x9C03 +,0xBC40 +,0x5C01 +,0xBC40 +,0xAC01 +,0xBC40 +,0xB401 +,0xBC40 +,0x7405 +,0xBC40 +,0xA406 +,0x8C69 +,0xA304 +,0x02B5 +,0xBC23 +,0x02B5 +,0xBC22 +,0x31C4 +,0xB046 +,0xFFF9 +,0xFA52 +,0xDFE4 +,0xBC02 +,0x1E36 +,0x7000 +,0x4FE0 +,0xB030 +,0x000B +,0xBC20 +,0x31C3 +,0xB046 +,0xFFF7 +,0xFA12 +,0xCF80 +,0xDF84 +,0xBC02 +,0x1E36 +,0x7000 +,0x4F80 +,0x6D31 +,0xCFA0 +,0xBC22 +,0x31C6 +,0xB046 +,0xFFF8 +,0xFA52 +,0xDF84 +,0xBC02 +,0x1E36 +,0x7000 +,0x4F80 +,0xB030 +,0x000C +,0xBC20 +,0x31C5 +,0xB046 +,0xFFF6 +,0xFA12 +,0xCFC0 +,0xDF84 +,0xBC02 +,0x1E36 +,0x6E05 +,0x0F81 +,0xB032 +,0x000E +,0xBC40 +,0x788F +,0x7000 +,0x61CE +,0xB040 +,0xFFF3 +,0x88D8 +,0xBC22 +,0x31C7 +,0xB066 +,0xFFF3 +,0xCF20 +,0xFA52 +,0xDE65 +,0xDF26 +,0xDF83 +,0xBC02 +,0x1E36 +,0xCF80 +,0xCF01 +,0xBC47 +,0xA803 +,0xBC47 +,0x5804 +,0x6112 +,0xCE7E +,0x6C33 +,0x0F21 +,0x241B +,0xBC47 +,0xA004 +,0x6847 +,0x24DE +,0xDEE3 +,0x8F03 +,0xBC23 +,0x31C9 +,0x4001 +,0x8C05 +,0xFA72 +,0xBC23 +,0x31C8 +,0x4001 +,0xFA72 +,0xB030 +,0xFFFE +,0xB046 +,0xFFF6 +,0xCF60 +,0xBC02 +,0x1E36 +,0xBC21 +,0x02A8 +,0xBC20 +,0x31C1 +,0xCF1E +,0xBC40 +,0x4083 +,0xFA10 +,0xBC40 +,0x649E +,0x2098 +,0x8F09 +,0xBC20 +,0x31C2 +,0xBC40 +,0x5083 +,0xFA10 +,0x6406 +,0x0F55 +,0x0018 +,0x8C03 +,0xBC40 +,0x5480 +,0xCF55 +,0x8E00 +,0x8EC0 +,0xE9F2 +,0x8E00 +,0xBC23 +,0x00A5 +,0xBC20 +,0x3054 +,0x6E10 +,0xE181 +,0xB800 +,0x2074 +,0x24A1 +,0xA201 +,0x045F +,0x28C8 +,0x6911 +,0x2902 +,0xBC21 +,0x00A3 +,0x6E10 +,0x654E +,0xBC24 +,0x2081 +,0xE085 +,0xBC26 +,0x2083 +,0xB801 +,0x2837 +,0x692F +,0x65CF +,0xDFC3 +,0xFAD3 +,0x28D8 +,0x2444 +,0xBC23 +,0x00A1 +,0x6E10 +,0xE54E +,0xE185 +,0xE1C6 +,0x692D +,0x64CF +,0x28E0 +,0x2444 +,0xA200 +,0x00A0 +,0x7008 +,0xA54E +,0x6220 +,0xA5CF +,0xBC24 +,0x2080 +,0x26A0 +,0xFA94 +,0xBC22 +,0x00A7 +,0x8F0E +,0x38A2 +,0x8E00 +,0xE286 +,0xE2C7 +,0x24BE +,0xBC26 +,0x3055 +,0x8E00 +,0xFAD6 +,0x28E6 +,0x2444 +,0x8E00 +,0xA30E +,0x00A7 +,0xE6CF +,0xBC24 +,0x3053 +,0x8E00 +,0xFA94 +,0x2244 +,0x8F3A +,0x7007 +,0x8FC4 +,0xA20E +,0x00A5 +,0xE24F +,0x88C8 +,0xA20E +,0x00A1 +,0x690B +,0x21CF +,0x88B8 +,0xA20E +,0x00A3 +,0xE0CF +,0x8898 +,0xBC26 +,0x3056 +,0xE10E +,0xFAD6 +,0x6807 +,0xA14F +,0x88A8 +,0x8F10 +,0xBC26 +,0x3057 +,0x8E00 +,0xFAD6 +,0x200E +,0x8F0A +,0xBC26 +,0x3059 +,0x8E00 +,0xFAD6 +,0x212E +,0x8F04 +,0xBC25 +,0x3058 +,0x8E00 +,0xFAB5 +,0x2095 +,0x8F03 +,0x8E00 +,0x8C06 +,0xA31E +,0x008C +,0x403E +,0x8E00 +,0xA31E +,0x008C +,0x403C +,0xA303 +,0x009C +,0xA301 +,0x009D +,0xA304 +,0x009E +,0xA302 +,0x009F +,0xA31C +,0x008B +,0xE9FE +,0x8EC0 +,0x3401 +,0xA300 +,0x00A0 +,0x6C84 +,0xA904 +,0xFA13 +,0x6E0D +,0x1FD5 +,0xBC22 +,0x3104 +,0xB002 +,0xFFFD +,0xFA52 +,0xBC21 +,0x7FFF +,0x6622 +,0xA443 +,0x40A1 +,0xBC23 +,0x02CE +,0xBC24 +,0x045A +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xE906 +,0xA202 +,0x02D3 +,0x6E0D +,0x1F81 +,0xB012 +,0xFFFB +,0x6988 +,0x5FA1 +,0xDFD5 +,0x8F04 +,0xBC20 +,0x2080 +,0x4021 +,0x8C0F +,0xA301 +,0x02D3 +,0xFA11 +,0xBC02 +,0x1E46 +,0xA201 +,0x0474 +,0x1A41 +,0x7007 +,0x9F61 +,0xBC20 +,0x2080 +,0xA31E +,0x02D3 +,0xFB11 +,0x7040 +,0x4F83 +,0xBC22 +,0x3104 +,0x6C8C +,0xBA10 +,0xFA52 +,0xBC23 +,0x7FFF +,0x6626 +,0x9F60 +,0xCFA0 +,0xBC23 +,0x02D1 +,0xBC24 +,0x045B +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FA +,0x8E00 +,0xE902 +,0xFA31 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x1E46 +,0xCFC1 +,0xDFC0 +,0xFA31 +,0xBC02 +,0x1E46 +,0xCFC1 +,0x1A48 +,0xA200 +,0x02D5 +,0xA202 +,0x045C +,0x0E41 +,0x26A0 +,0xA301 +,0x02D5 +,0x8F06 +,0xBC21 +,0x2082 +,0x401E +,0xA200 +,0x02D5 +,0xA31E +,0x02D5 +,0xFB30 +,0x6D14 +,0x4FF5 +,0xE9FE +,0x40E0 +,0x8EC0 +,0x0848 +,0xA301 +,0x045C +,0x6C84 +,0xBA10 +,0xE904 +,0xB580 +,0x0002 +,0xA201 +,0x0474 +,0xB100 +,0x00BE +,0xBC23 +,0x2081 +,0x66C2 +,0x1FD5 +,0xBC22 +,0x3104 +,0x6E2D +,0x3B74 +,0xB00A +,0xFFFD +,0xFA52 +,0xBC23 +,0x7FFF +,0x6626 +,0xA444 +,0x40C1 +,0xBC23 +,0x02D6 +,0xBC24 +,0x045D +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xE904 +,0xFA10 +,0x6E08 +,0x1FC1 +,0xDFF5 +,0xBC02 +,0x1E46 +,0xA201 +,0x0474 +,0xBC22 +,0x3104 +,0x6692 +,0x0FC0 +,0xBC23 +,0x2083 +,0x6C80 +,0xBA52 +,0xBC24 +,0x7FFF +,0x6E05 +,0x3B71 +,0x6628 +,0x9FA1 +,0xB000 +,0xFFFD +,0x40E1 +,0xBC23 +,0x02D9 +,0xBC24 +,0x045E +,0xBC02 +,0x1E36 +,0xCFF5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0x0000 +,0xBC21 +,0x00A9 +,0x4402 +,0xE083 +,0xE0C4 +,0x24A3 +,0xBC23 +,0x213F +,0x8E00 +,0x6960 +,0x3A74 +,0x8A0E +,0x6A38 +,0xBA74 +,0xB300 +,0x0044 +,0x28E2 +,0x8F0B +,0x2600 +,0x8F04 +,0x2444 +,0x8EC0 +,0xA30E +,0x00A9 +,0xE4CF +,0x4000 +,0x8EC0 +,0xA300 +,0x00A9 +,0xE4C0 +,0x8880 +,0x8EC0 +,0x8E00 +,0xA300 +,0x045F +,0xE904 +,0xBC21 +,0x2022 +,0x6E05 +,0x1FD5 +,0xA21C +,0x047A +,0xB000 +,0xFFFD +,0xFA35 +,0x7000 +,0x6445 +,0xDFFC +,0xBC22 +,0x0780 +,0xBC23 +,0x02DD +,0xBC24 +,0x02DF +,0xBC02 +,0x1E36 +,0xA201 +,0x02DF +,0xA200 +,0x02DC +,0xCFE2 +,0xA092 +,0x8000 +,0xB000 +,0xFFFF +,0xA301 +,0x047A +,0x2680 +,0xA300 +,0x02DC +,0x8F34 +,0xBC20 +,0x304D +,0xBC3E +,0x0320 +,0xBC3A +,0x7FFF +,0xFA10 +,0xA202 +,0x047C +,0xA31E +,0x02DC +,0xA31A +,0x047A +,0x21C8 +,0x8F14 +,0xBC20 +,0x304E +,0xBC23 +,0x304F +,0xFA10 +,0x6872 +,0x3A70 +,0x8F03 +,0x2048 +,0x8F01 +,0x26A0 +,0x8F05 +,0x21C8 +,0x8F0A +,0x4000 +,0xA300 +,0x047C +,0x8D07 +,0x4040 +,0x8C05 +,0xA300 +,0x047C +,0x4020 +,0xA300 +,0x047C +,0xA200 +,0x047C +,0x2242 +,0x4000 +,0x8F02 +,0xA300 +,0x047B +,0x8C07 +,0xCFD5 +,0x7008 +,0x0FD5 +,0x8C03 +,0xA300 +,0x047B +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xBC20 +,0x2021 +,0xA201 +,0x047C +,0x6984 +,0x3A12 +,0x8F1B +,0x2611 +,0xB034 +,0xFFE0 +,0x8F10 +,0x2692 +,0x8F1B +,0xBC21 +,0x3051 +,0x8E00 +,0xFA31 +,0x20D1 +,0x8F00 +,0xA026 +,0x4000 +,0x21D1 +,0x8F11 +,0xB024 +,0x0020 +,0xA0A4 +,0x4000 +,0x8D0E +,0xBC21 +,0x3052 +,0x8E00 +,0xFA31 +,0x8C09 +,0xA026 +,0x4000 +,0xBC21 +,0x3050 +,0xB024 +,0x0020 +,0xFA31 +,0xA0A4 +,0x4000 +,0x8EC0 +,0xFB12 +,0x8E00 +,0x0000 +,0xBC22 +,0x3105 +,0xE902 +,0xA21C +,0x0326 +,0x77FE +,0xBA52 +,0x6EF0 +,0x9FDC +,0xA200 +,0x0312 +,0xBC3C +,0x02E0 +,0xBC22 +,0x30C2 +,0xBC23 +,0x8EE4 +,0xBC24 +,0x771E +,0xBC25 +,0x88E2 +,0x403B +,0x706F +,0xE800 +,0xBD05 +,0x11DA +,0x6E30 +,0xBC19 +,0x2442 +,0x6960 +,0x3AC7 +,0x8A08 +,0xBB3D +,0x8E19 +,0x28CF +,0xA207 +,0x0315 +,0xBC21 +,0x12EB +,0xA206 +,0x0316 +,0x28F9 +,0x28F3 +,0xA307 +,0x0316 +,0x88F0 +,0x2442 +,0x28FC +,0x28F5 +,0xA307 +,0x0315 +,0x417A +,0x88E0 +,0xA207 +,0x0317 +,0x699C +,0xEA18 +,0x2442 +,0x4001 +,0x8F00 +,0xB01E +,0xFFFF +,0x6A3C +,0x4FC1 +,0x88E4 +,0xBC3D +,0x0318 +,0x5FFA +,0x7007 +,0x64E6 +,0xA206 +,0x0317 +,0x6998 +,0xDFC1 +,0x8F02 +,0x35B1 +,0x3BA6 +,0x8E00 +,0xA31D +,0x0317 +,0xA300 +,0x0312 +,0xCFC2 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0326 +,0x0000 +,0xA200 +,0x0325 +,0xA201 +,0x0354 +,0xBC3D +,0x0327 +,0x459F +,0x403B +,0xBC3C +,0x0318 +,0x41BE +,0xBC22 +,0x30CB +,0xBD05 +,0x1200 +,0x5FFA +,0x3862 +,0x6910 +,0xBC1D +,0x6960 +,0x3A64 +,0x8A03 +,0xBBB0 +,0xC81D +,0x28EC +,0x88B0 +,0x40DA +,0xE4E3 +,0xEA18 +,0xA300 +,0x0325 +,0xA200 +,0x0353 +,0x3B9D +,0x459E +,0xBC22 +,0x30CF +,0x5FFA +,0xA301 +,0x0354 +,0x6910 +,0xBA43 +,0xE064 +,0x8A27 +,0xBB8C +,0x861C +,0x403A +,0x28E3 +,0x88A0 +,0xEA18 +,0x8EC0 +,0xA300 +,0x0353 +,0xA302 +,0x0355 +,0xBC25 +,0x0357 +,0xBC22 +,0x30F8 +,0x6E09 +,0x7CA4 +,0xB800 +,0xA6B6 +,0x24B4 +,0xA206 +,0x0356 +,0x33B0 +,0x4FE4 +,0xBC27 +,0x01FF +,0x35B1 +,0x1927 +,0x09F4 +,0xBC24 +,0x0100 +,0x4806 +,0x1926 +,0xA206 +,0x0355 +,0x2670 +,0xA307 +,0x0356 +,0x243E +,0x28FC +,0x2444 +,0x4004 +,0x7008 +,0x64CE +,0x6673 +,0x26CF +,0x2670 +,0x8F2C +,0xBC27 +,0x30F7 +,0xE2CF +,0xFAF7 +,0x6CDC +,0x26C4 +,0xA20E +,0x0357 +,0xA304 +,0x0357 +,0x88D8 +,0x8F1C +,0x3230 +,0x8F01 +,0xB036 +,0xFFFF +,0xFB53 +,0xA202 +,0x0359 +,0x2620 +,0x8F0D +,0x2622 +,0x4043 +,0x8F05 +,0xB20A +,0x099A +,0x189A +,0xB22A +,0x21EC +,0x8C08 +,0x18A2 +,0xB22A +,0x13D7 +,0x8C04 +,0x188A +,0xB20A +,0x17AE +,0x188A +,0x8C07 +,0xA302 +,0x0359 +,0xBC22 +,0x30F7 +,0xB03E +,0xFFFF +,0xFB53 +,0xA202 +,0x0359 +,0x144A +,0x2442 +,0x28F1 +,0x8894 +,0x8EC0 +,0x8E00 +,0xE441 +,0xBC22 +,0x2131 +,0xBC23 +,0x00B0 +,0xBC24 +,0x2135 +,0x6915 +,0x3B53 +,0xFA93 +,0xBC22 +,0x2136 +,0xE4C3 +,0xB800 +,0xA210 +,0xBC80 +,0x4000 +,0x6915 +,0xE902 +,0xBC21 +,0x30F9 +,0xA203 +,0x035B +,0xBC22 +,0x035C +,0x6E73 +,0xFA31 +,0xBC24 +,0x30FA +,0x28C1 +,0xA300 +,0x035B +,0xFA94 +,0x6E08 +,0xBC40 +,0x6A37 +,0x2143 +,0x2A83 +,0x88C0 +,0xDFCE +,0xDFEF +,0xBC20 +,0x0A30 +,0xBC88 +,0x0000 +,0xCFCE +,0xA300 +,0x035A +,0xCFEF +,0x2444 +,0xA203 +,0x035E +,0xB580 +,0x0001 +,0x6000 +,0xE4CE +,0xB000 +,0x2000 +,0xE54F +,0xA300 +,0x035E +,0xBC21 +,0x3244 +,0xBC80 +,0x4000 +,0xBC21 +,0x2111 +,0x8EC0 +,0xE9FE +,0xFB30 +,0xBC22 +,0x3105 +,0xBC24 +,0x30FB +,0xE906 +,0xA203 +,0x035A +,0xBC25 +,0xF000 +,0xFA52 +,0xFA94 +,0xA21E +,0x0314 +,0xA21C +,0x015F +,0x66BA +,0xDF84 +,0xDFA2 +,0x7050 +,0xDF63 +,0xDFDC +,0xDF5E +,0xBC22 +,0x0CCD +,0xBC24 +,0x2131 +,0xBC25 +,0x199A +,0xBC3B +,0x009C +,0xBC3D +,0x02E0 +,0xBD0A +,0x131D +,0xA206 +,0x035F +,0x700E +,0x8F67 +,0x63ED +,0xCFBE +,0xB47C +,0x000E +,0xB11E +,0x0005 +,0xA200 +,0x0360 +,0x0E08 +,0x2810 +,0xB5FE +,0x000E +,0x380E +,0x1BB7 +,0xB000 +,0x0400 +,0xBCF0 +,0xC000 +,0xA306 +,0x035F +,0xBCED +,0x4000 +,0x283A +,0xA307 +,0x0360 +,0x888C +,0xBC27 +,0x00B1 +,0x6EE7 +,0x7B97 +,0x606C +,0x0F40 +,0xBC27 +,0x3244 +,0xBCED +,0xC000 +,0x7016 +,0xBC1F +,0x6EE6 +,0xDF40 +,0xBC20 +,0x2135 +,0xBC21 +,0x2111 +,0xFA10 +,0xBC8E +,0x0000 +,0xFB36 +,0xB560 +,0x0001 +,0xCF80 +,0xBC8C +,0x0000 +,0xBC3E +,0x00C2 +,0x63E1 +,0x8FC0 +,0x3F3E +,0xFF18 +,0xDFC0 +,0xCFC2 +,0xA302 +,0x015F +,0xCF43 +,0x8EC0 +,0xE9FA +,0xA303 +,0x0314 +,0xA203 +,0x0366 +,0x6D06 +,0x6044 +,0xBC22 +,0x0367 +,0xA203 +,0x0363 +,0x08C3 +,0xA206 +,0x0355 +,0x6E00 +,0xBC45 +,0xBCC9 +,0x8000 +,0x698C +,0x2146 +,0x24B5 +,0xA205 +,0x0364 +,0x28E5 +,0x2444 +,0xA303 +,0x0366 +,0x7000 +,0x244E +,0x7008 +,0xE54F +,0x1918 +,0x2640 +,0x8F4A +,0xE14F +,0xA20E +,0x0367 +,0xE540 +,0xA300 +,0x0367 +,0xBC22 +,0x3101 +,0xE0C1 +,0x2409 +,0xFA52 +,0x88C8 +,0x218A +,0x240C +,0x3840 +,0x8F0B +,0xBC20 +,0x2004 +,0x8E00 +,0xFA10 +,0x2680 +,0x3802 +,0x8F04 +,0xBC20 +,0x3100 +,0x5FE4 +,0xFA10 +,0x2108 +,0x181C +,0xA201 +,0x0369 +,0xA204 +,0x0365 +,0x3449 +,0x084C +,0xBC24 +,0x30FE +,0x2610 +,0xA301 +,0x0369 +,0xA201 +,0x0362 +,0xFA94 +,0x195A +,0x0048 +,0x3340 +,0x8F12 +,0x2650 +,0x8F14 +,0xBC20 +,0x3103 +,0xA204 +,0x0361 +,0x69B0 +,0x3A10 +,0x8F02 +,0x2188 +,0x8C04 +,0x185A +,0x0410 +,0x2088 +,0x1853 +,0xA301 +,0x0361 +,0x3822 +,0x8D05 +,0xBC20 +,0x30FE +,0xB028 +,0xFFFF +,0xFB12 +,0x8EC0 +,0xA301 +,0x0362 +,0x8E00 +,0x8EB8 +,0xBC20 +,0x303D +,0x4021 +,0xFA10 +,0xA202 +,0x0462 +,0x1408 +,0x3491 +,0xB000 +,0xFFFF +,0x0810 +,0x2680 +,0xA300 +,0x0462 +,0xA200 +,0x0460 +,0x8F36 +,0xBC23 +,0x3041 +,0xBC22 +,0x3040 +,0x6980 +,0x3A73 +,0xA204 +,0x045B +,0xA21C +,0x045A +,0xFA52 +,0x8F06 +,0x21A3 +,0x8F02 +,0x387C +,0x201A +,0x8F07 +,0x4000 +,0x8D06 +,0x21A3 +,0x8F03 +,0x387C +,0x219A +,0x8F00 +,0x3801 +,0xBC22 +,0x3043 +,0x8E00 +,0xFA52 +,0x2620 +,0x8F17 +,0xA202 +,0x0465 +,0x26A0 +,0x8F12 +,0xBC22 +,0x2004 +,0x8E00 +,0xFA52 +,0x26A0 +,0x8F0C +,0xBC22 +,0x303F +,0xA203 +,0x045E +,0xFA52 +,0x209A +,0x8F05 +,0xBC22 +,0x303E +,0xA203 +,0x045D +,0xFA52 +,0x211A +,0x8F00 +,0x4000 +,0xBC22 +,0x3044 +,0xA300 +,0x0460 +,0xFA50 +,0xA202 +,0x0463 +,0x2680 +,0x8F03 +,0x4000 +,0x8C42 +,0xA300 +,0x0461 +,0xBC20 +,0x2015 +,0xBC23 +,0x3048 +,0xFA10 +,0xFA73 +,0x2003 +,0x4000 +,0x3860 +,0x8F1A +,0xBC20 +,0x2080 +,0xBC24 +,0x3046 +,0xFA10 +,0xFA94 +,0x2184 +,0x3803 +,0x8F07 +,0xBC20 +,0x3047 +,0xBC24 +,0x2015 +,0xFA10 +,0xFA94 +,0x2020 +,0x3803 +,0x8F08 +,0xBC20 +,0x2083 +,0xBC24 +,0x3045 +,0xFA10 +,0xFA94 +,0x2004 +,0x3803 +,0x8F00 +,0x3801 +,0x2680 +,0x8F02 +,0xBC20 +,0x304A +,0x8C05 +,0xFA10 +,0xBC20 +,0x3049 +,0x8E00 +,0xFA10 +,0xBC24 +,0x304B +,0x0E10 +,0xFA92 +,0x2102 +,0x8F04 +,0xBC22 +,0x304C +,0x8E00 +,0xFA52 +,0x2002 +,0x1890 +,0x33A0 +,0x180B +,0xA300 +,0x0461 +,0xBC20 +,0x3042 +,0xA201 +,0x0461 +,0xA203 +,0x0460 +,0xB512 +,0x0001 +,0xFA10 +,0xA302 +,0x0463 +,0x0059 +,0x2600 +,0x8F0A +,0x2601 +,0x8F07 +,0x2602 +,0x4042 +,0x8F02 +,0x2603 +,0x8C04 +,0x1851 +,0x8C02 +,0x4001 +,0x4021 +,0xBC20 +,0x200D +,0x8EC0 +,0x8E00 +,0xFB11 +,0xBC20 +,0x0375 +,0xBC21 +,0x0372 +,0xBC22 +,0x036A +,0xBC3C +,0x0376 +,0x700E +,0xA0C1 +,0x70CF +,0xA040 +,0xBC23 +,0x038F +,0xBC09 +,0x1482 +,0x2442 +,0xE104 +,0xBC26 +,0x1180 +,0x6A39 +,0xA185 +,0xBC21 +,0xF2C0 +,0x6A3A +,0x61C7 +,0x6A3F +,0xA5A5 +,0xE584 +,0xE184 +,0xE185 +,0xBC21 +,0x1CF0 +,0x6A3A +,0x61C7 +,0xBC21 +,0x8620 +,0x6A3E +,0x65A5 +,0x88C0 +,0x2442 +,0x6A39 +,0xA584 +,0xBC21 +,0x0840 +,0x6A3A +,0x6184 +,0x6A3F +,0xA185 +,0xBC21 +,0x0A40 +,0x6A3A +,0x61C7 +,0xBC21 +,0x8620 +,0x6A3E +,0x65A5 +,0x88C0 +,0x8E00 +,0xE584 +,0xE464 +,0xBC23 +,0x038F +,0xBC21 +,0x0375 +,0x8E00 +,0xE4C0 +,0x8EB8 +,0x0000 +,0xA202 +,0x0372 +,0xA203 +,0x0395 +,0x009A +,0xB214 +,0x0014 +,0x8F16 +,0xB024 +,0xFFEC +,0x5FC3 +,0x04DA +,0x3B43 +,0xA200 +,0x0375 +,0xBC3C +,0x0376 +,0x433E +,0xBC23 +,0x305B +,0x77F6 +,0xAA18 +,0x6910 +,0xBA64 +,0xE065 +,0x8A05 +,0xBBB0 +,0xC81D +,0x4023 +,0x8880 +,0xA303 +,0x0373 +,0x8EC0 +,0xA302 +,0x0395 +,0x8E00 +,0xBC20 +,0x03BA +,0xA203 +,0x03B9 +,0x6D20 +,0xA00E +,0xB206 +,0x0080 +,0xE04F +,0xE14C +,0x8F36 +,0x88B0 +,0x40A4 +,0xB226 +,0x01B0 +,0x40C5 +,0x1925 +,0x401C +,0xB226 +,0x06C0 +,0x7007 +,0xA45C +,0x4083 +,0x6607 +,0x255E +,0xA205 +,0x0396 +,0xA202 +,0x03BE +,0xA31C +,0x03B9 +,0xA31C +,0x03BA +,0x2268 +,0x8F03 +,0x8E00 +,0x8C03 +,0xB034 +,0xFFFF +,0x34D1 +,0xA300 +,0x0396 +,0xA202 +,0x03BD +,0xB236 +,0x000A +,0x8F05 +,0xB226 +,0xFFF6 +,0x3B83 +,0x8F04 +,0x4002 +,0x401C +,0x8D02 +,0x4022 +,0x401C +,0x26A1 +,0x8F00 +,0x40A0 +,0xA31C +,0x03BE +,0xA302 +,0x03BD +,0x8C0D +,0xA300 +,0x0397 +,0x2421 +,0xBC25 +,0x1000 +,0x28E5 +,0x34D9 +,0xA303 +,0x03B9 +,0xA30E +,0x03BA +,0xE44F +,0xE54C +,0xA200 +,0x0397 +,0x3048 +,0xBC20 +,0x7E7E +,0x8EC0 +,0xBC82 +,0x0000 +,0x8E00 +,0xBC22 +,0x2131 +,0xBC24 +,0x00B2 +,0x77F6 +,0xBB54 +,0xBC23 +,0x2135 +,0xBC22 +,0x2136 +,0x7087 +,0xBA73 +,0x6910 +,0xFA52 +,0xBCB2 +,0xC000 +,0xBCA2 +,0x8000 +,0xA200 +,0x03A6 +,0x3F1A +,0xBC22 +,0x3060 +,0xBC3C +,0x03A8 +,0x6910 +,0xBF10 +,0xE902 +,0xFA43 +,0x6960 +,0x3E18 +,0x8A06 +,0xBF8C +,0x8618 +,0xBF8C +,0xA410 +,0x2A42 +,0xBC23 +,0x03C4 +,0x88D0 +,0x6D26 +,0xA19E +,0xBC27 +,0x03C7 +,0x6E62 +,0xE15A +,0x6E7A +,0x5FC2 +,0x6E72 +,0x21DC +,0x88A0 +,0x6D4E +,0xA38E +,0xA206 +,0x03A5 +,0xA300 +,0x03A6 +,0x6998 +,0x23CF +,0xE24C +,0xDFE5 +,0x8F03 +,0x8E00 +,0x8C16 +,0xB06C +,0xFFFF +,0x88E0 +,0x39FC +,0x39DE +,0x399A +,0x8880 +,0xBC21 +,0x2045 +,0x2442 +,0x7007 +,0xBB30 +,0xBC20 +,0x2046 +,0xBC21 +,0x305A +,0x7009 +,0xBB16 +,0x7007 +,0x3A30 +,0x3B4C +,0x15B0 +,0x240A +,0x4020 +,0x28C8 +,0xBC21 +,0x03BF +,0xE7CF +,0xA30E +,0x03C7 +,0xBCAA +,0x8000 +,0xA306 +,0x03A5 +,0x690B +,0x60C6 +,0x6E20 +,0x664C +,0x6E7F +,0x2482 +,0x6E77 +,0xA0C7 +,0x6E66 +,0xA4C6 +,0x6A3A +,0x0FC1 +,0xBC20 +,0x3068 +,0x6915 +,0x24CC +,0xA30E +,0x03C4 +,0x6915 +,0xE5CF +,0x6915 +,0xBA01 +,0x6A34 +,0x7A02 +,0x6A3C +,0xBA02 +,0xBC40 +,0x1205 +,0x6A3E +,0xBA02 +,0x6A3A +,0xBA16 +,0xBC40 +,0x1A03 +,0x6A3A +,0x8FE0 +,0x28DE +,0x88A0 +,0xBC40 +,0x1E05 +,0xBC40 +,0x1602 +,0xBC23 +,0x28BE +,0xA204 +,0x03C3 +,0xBCA4 +,0xC000 +,0xB038 +,0x4000 +,0x009A +,0xA302 +,0x03C3 +,0xBC23 +,0x3244 +,0xBCA4 +,0xC000 +,0xBC23 +,0x2111 +,0x8EC0 +,0xE9FE +,0xFB72 +,0xA200 +,0x0398 +,0x2457 +,0xBC22 +,0x306D +,0x77FE +,0xA441 +,0xBC3C +,0x0399 +,0x7067 +,0xBA43 +,0x6E73 +,0xE800 +,0x6915 +,0x3C1C +,0x8A0A +,0xBB8C +,0x861C +,0xBB8C +,0xA413 +,0x28DA +,0xA300 +,0x0398 +,0x8EC0 +,0x8880 +,0x8E00 +,0xE902 +,0xA203 +,0x0372 +,0x6CAC +,0x1FD5 +,0x8F06 +,0xBC20 +,0x036A +,0xBC21 +,0x213E +,0xBC0B +,0x15CB +,0xFA32 +,0xE402 +,0xBC02 +,0x1445 +,0xBC02 +,0x148A +,0xA201 +,0x0372 +,0x41E3 +,0xA202 +,0x0373 +,0x0459 +,0x2621 +,0xA301 +,0x0372 +,0x8F07 +,0x26A2 +,0x8F1A +,0xA200 +,0x0374 +,0xBC02 +,0x1AEC +,0x4002 +,0x8D16 +,0x3820 +,0xBC02 +,0x14AE +,0x3820 +,0xBC02 +,0x1504 +,0xA201 +,0x03B8 +,0x2610 +,0x8F04 +,0xB002 +,0xFFFF +,0x4002 +,0x8C08 +,0xA300 +,0x03B8 +,0x3820 +,0xBC02 +,0x15A4 +,0xA300 +,0x0374 +,0x4042 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0373 +,0x3E02 +,0xBC20 +,0x03E5 +,0x3820 +,0xE002 +,0xE003 +,0xE044 +,0xE402 +,0xE484 +,0xE042 +,0xE482 +,0x7008 +,0xA443 +,0xA200 +,0x03E4 +,0x0C10 +,0xA300 +,0x03E4 +,0x3E01 +,0x8EB8 +,0xBC20 +,0x30BF +,0xA201 +,0x0447 +,0xFA10 +,0x6852 +,0x2902 +,0xBC22 +,0x30BB +,0xBC23 +,0x30BD +,0x18D3 +,0xA202 +,0x0449 +,0xFA64 +,0x3491 +,0x6835 +,0x3A73 +,0x8F65 +,0xA202 +,0x0448 +,0x2153 +,0x8F07 +,0x3449 +,0x3401 +,0xA080 +,0x4000 +,0x4002 +,0x8C5B +,0xA300 +,0x0447 +,0xBC20 +,0x30C1 +,0xA201 +,0x03CF +,0xBC22 +,0x30BA +,0x6114 +,0x5FF5 +,0x701F +,0x3A10 +,0x4023 +,0x6220 +,0xDFDC +,0xB412 +,0x0001 +,0x2620 +,0x8F04 +,0x7000 +,0x5FC1 +,0xA301 +,0x03CB +,0xA301 +,0x03CC +,0xBC22 +,0x30C0 +,0xA201 +,0x03D6 +,0x3449 +,0xFA52 +,0x20CA +,0xA301 +,0x03D6 +,0x8F19 +,0x4041 +,0x0801 +,0x2600 +,0x8F13 +,0x3E02 +,0x4000 +,0xA300 +,0x0099 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0xFF7F +,0xFA12 +,0x0851 +,0x7008 +,0x3B11 +,0xBC02 +,0x05B3 +,0x7010 +,0x4FC0 +,0x8C05 +,0xA301 +,0x009A +,0x8C02 +,0x4060 +,0xCFC0 +,0x3302 +,0x8F18 +,0x3541 +,0xBC21 +,0x1111 +,0x2829 +,0x3200 +,0x380E +,0x8F0D +,0x70F0 +,0x4FF5 +,0xBC22 +,0x2042 +,0xBC23 +,0x2041 +,0xBC24 +,0xEEEF +,0xBC0D +,0x1681 +,0xFB51 +,0x6008 +,0x3B70 +,0x8C06 +,0x4002 +,0x8C04 +,0x7000 +,0x8FF5 +,0x7000 +,0x8FF5 +,0xA302 +,0x0448 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0449 +,0xA200 +,0x03CE +,0xB300 +,0x6600 +,0x4020 +,0x3820 +,0x8F00 +,0xA200 +,0x044A +,0x2681 +,0xA300 +,0x044A +,0x8F27 +,0xA200 +,0x03D2 +,0x2600 +,0xBC22 +,0x2044 +,0x4000 +,0x1801 +,0xFA53 +,0x0118 +,0xBC23 +,0x2043 +,0xFB54 +,0xFA72 +,0x0448 +,0x0091 +,0xA204 +,0x03D5 +,0xFB72 +,0xB5C8 +,0x0001 +,0x0061 +,0xA202 +,0x044C +,0x004A +,0xBC23 +,0x2042 +,0xA204 +,0x0448 +,0xA300 +,0x03D2 +,0xBC22 +,0x2041 +,0xA205 +,0x03CA +,0x0020 +,0xFB71 +,0xA300 +,0x0448 +,0xFB55 +,0xBC00 +,0x1612 +,0x8EB8 +,0xA201 +,0x03D5 +,0x3312 +,0xA201 +,0x03CE +,0x8F0A +,0xB312 +,0x3F00 +,0x8F07 +,0xA202 +,0x03D4 +,0x224A +,0x8F04 +,0x4001 +,0x7008 +,0x2441 +,0xA300 +,0x03D0 +,0x8EB8 +,0x2680 +,0xA200 +,0x03CF +,0x8F0A +,0xFA11 +,0xB312 +,0x0198 +,0x8F05 +,0xA201 +,0x03D3 +,0x1641 +,0x40A2 +,0x2E4A +,0x8F00 +,0x3401 +,0x3402 +,0xBC21 +,0x30BB +,0x2041 +,0x8F04 +,0x4000 +,0xA300 +,0x03D0 +,0xBC20 +,0x30B3 +,0xA201 +,0x03D0 +,0x2611 +,0x4001 +,0x8F00 +,0xFA11 +,0xA300 +,0x03CF +,0x8EC0 +,0xB592 +,0x0006 +,0xA301 +,0x03CE +,0x6EF5 +,0x6080 +,0xE906 +,0x7007 +,0x20C1 +,0xA204 +,0x03CE +,0x6313 +,0x1F83 +,0x65B0 +,0x5FA2 +,0x65C0 +,0x1FE3 +,0x7000 +,0x9FC0 +,0x4020 +,0x4207 +,0x5FE6 +,0xBC23 +,0xC6C0 +,0xBC21 +,0x6E40 +,0x38A2 +,0xBC0F +,0x1720 +,0x2F68 +,0x2F20 +,0x8F00 +,0x0D6B +,0x2FB0 +,0x8F00 +,0x0D69 +,0x1785 +,0x3491 +,0x4044 +,0x6815 +,0x0FE4 +,0x4147 +,0x8FEE +,0x6E1D +,0x0FA2 +,0xB036 +,0xFFFB +,0x69A8 +,0x5FE3 +,0x8F08 +,0xB42A +,0x0006 +,0xBC23 +,0x03FF +,0x0893 +,0xA31C +,0x03D5 +,0xDF62 +,0xA302 +,0x03D2 +,0x7000 +,0x8F83 +,0xBC21 +,0x7F80 +,0x3882 +,0xBD10 +,0x174F +,0x2E90 +,0x2F68 +,0x2FB0 +,0x8F0B +,0x26B1 +,0x8F02 +,0x09E9 +,0x2670 +,0x8F03 +,0xBC26 +,0x6E40 +,0x0D6E +,0x8C03 +,0x1785 +,0x3521 +,0x3491 +,0x8E00 +,0xCFA0 +,0x2601 +,0xBC20 +,0x03FF +,0x8F27 +,0xB41A +,0x0006 +,0x0808 +,0x2680 +,0x8F01 +,0x32C2 +,0x8F00 +,0x403C +,0x26B0 +,0xDF7C +,0x8F12 +,0xBC22 +,0x30B3 +,0x6E20 +,0x8FC3 +,0xBC21 +,0x30BB +,0xBD04 +,0x1772 +,0xFA86 +,0x6881 +,0xBA86 +,0x8F01 +,0x2246 +,0x8F03 +,0x21E1 +,0x1914 +,0xA304 +,0x03CF +,0x8E00 +,0x8D0B +,0xCFC0 +,0x6330 +,0x8FE0 +,0xA305 +,0x03D4 +,0xA304 +,0x03D5 +,0xBC02 +,0x16C7 +,0x8D01 +,0xCFC3 +,0x6EAF +,0x8F60 +,0xA303 +,0x03D3 +,0x8EC0 +,0xE9FA +,0xA305 +,0x03D4 +,0xB022 +,0x3098 +,0xA200 +,0x03D2 +,0x6980 +,0x3A45 +,0x8F26 +,0x4343 +,0x0519 +,0x4003 +,0xBC0C +,0x1799 +,0xFA46 +,0x0DAE +,0x2246 +,0x8F01 +,0x3882 +,0x3803 +,0x8E00 +,0x2680 +,0x8F18 +,0x2610 +,0x4046 +,0x4022 +,0x1996 +,0x4205 +,0x3290 +,0x0569 +,0xA306 +,0x03D5 +,0x8F02 +,0x3250 +,0x8F00 +,0x14D5 +,0xBC21 +,0x30A9 +,0x044C +,0x3210 +,0x8F01 +,0x1451 +,0x00D9 +,0xA201 +,0x03D3 +,0x0C4B +,0xA301 +,0x03D3 +,0x8EC0 +,0xA300 +,0x03D2 +,0x8E00 +,0xE904 +,0xA201 +,0x03CC +,0xA200 +,0x03CD +,0x7000 +,0x9F81 +,0xB000 +,0xFFFF +,0xA302 +,0x03CE +,0x6984 +,0x1FB5 +,0x8F4C +,0x2680 +,0x8F47 +,0xA201 +,0x03CF +,0x344A +,0xBC20 +,0x30BB +,0x21C8 +,0xBC20 +,0x30B3 +,0x1841 +,0x6E18 +,0x9FC1 +,0xBC21 +,0x03D7 +,0xBC02 +,0x1700 +,0xA201 +,0x03CF +,0x7000 +,0x8FC0 +,0xA204 +,0x0444 +,0x6882 +,0x1FC1 +,0x4023 +,0x8F06 +,0xB018 +,0xFFFF +,0x6CC7 +,0x9FC0 +,0x6626 +,0x9FE1 +,0x8C20 +,0xDF82 +,0x3422 +,0x6CE1 +,0x1FE0 +,0x181A +,0x2681 +,0xA300 +,0x03CB +,0x8F15 +,0xBC20 +,0x0444 +,0x8A09 +,0xE402 +,0xFA31 +,0xA21E +,0x03D3 +,0xB592 +,0x0006 +,0xA302 +,0x03D0 +,0xA303 +,0x03D1 +,0xA302 +,0x03D5 +,0xA302 +,0x03D2 +,0xA301 +,0x03CE +,0xA31E +,0x03CA +,0xBC02 +,0x1690 +,0xCFE2 +,0xCFC1 +,0xA302 +,0x0444 +,0xA301 +,0x03CF +,0x8C26 +,0x71A0 +,0x0F85 +,0x8C23 +,0xCF85 +,0x2600 +,0x4681 +,0x1848 +,0x7008 +,0x1FC1 +,0x2C48 +,0x401E +,0xBC21 +,0x03D9 +,0xBC20 +,0x03D7 +,0xA31E +,0x03CF +,0x1848 +,0x3862 +,0xBC02 +,0x1700 +,0xA202 +,0x03CF +,0x6988 +,0x0FC0 +,0x4025 +,0x8F09 +,0x0885 +,0x2620 +,0x4006 +,0x8F00 +,0xBC02 +,0x15FE +,0xA306 +,0x0444 +,0x8C02 +,0x4680 +,0xCF85 +,0xCFB5 +,0xA305 +,0x03CC +,0x8EC0 +,0xE9FC +,0xA300 +,0x03CD +,0xE902 +,0xA203 +,0x03CD +,0xB036 +,0xFFFF +,0x698C +,0x1FC3 +,0xDFF5 +,0xBC01 +,0x190F +,0xA201 +,0x03D1 +,0x2690 +,0xBC01 +,0x1920 +,0xB016 +,0xFFE6 +,0x4340 +,0x2048 +,0xBC01 +,0x190A +,0xB306 +,0x0019 +,0xBC01 +,0x18F4 +,0xA201 +,0x03D2 +,0xB306 +,0x0018 +,0x8F7E +,0xB306 +,0x0017 +,0x8F4E +,0xCFC3 +,0xB316 +,0x0016 +,0xBC01 +,0x1920 +,0xA203 +,0x044B +,0x26B0 +,0xBC01 +,0x1920 +,0x4023 +,0x2610 +,0xA303 +,0x044B +,0x4002 +,0x8F0F +,0xBC21 +,0x03D7 +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F07 +,0xA203 +,0x0444 +,0xA21E +,0x03D3 +,0x34D9 +,0xA31E +,0x03CA +,0xA303 +,0x0444 +,0xA203 +,0x0444 +,0xB236 +,0x0080 +,0x8F19 +,0xA203 +,0x0446 +,0xB236 +,0x0080 +,0x7000 +,0xCFC5 +,0xBC21 +,0x0444 +,0x8F09 +,0xA200 +,0x0445 +,0xB200 +,0x0080 +,0x8F12 +,0x8A03 +,0xE483 +,0x3569 +,0xBC02 +,0x15FE +,0x8D0D +,0x8A03 +,0xE483 +,0xB05A +,0xFFFF +,0xBC02 +,0x15FE +,0x8D06 +,0x7000 +,0xCFC5 +,0xBC21 +,0x0444 +,0x8A03 +,0xE483 +,0xA200 +,0x03D2 +,0xDFC5 +,0xBC02 +,0x16DA +,0xBC02 +,0x1690 +,0x8D73 +,0x2610 +,0xBC21 +,0x03D7 +,0x8F24 +,0xBC40 +,0x1880 +,0x4023 +,0x2E03 +,0xBC40 +,0x1C80 +,0x4002 +,0x185A +,0xA200 +,0x03D9 +,0x2E03 +,0x0001 +,0xA300 +,0x03D9 +,0xBC21 +,0x03D9 +,0x441A +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F0B +,0xA203 +,0x0445 +,0xA201 +,0x03D3 +,0x34D9 +,0xA301 +,0x03CA +,0xA31A +,0x044C +,0xA303 +,0x0445 +,0x8C04 +,0x4003 +,0x8C02 +,0x4003 +,0x4003 +,0x8C47 +,0xA303 +,0x044B +,0x2610 +,0xBC21 +,0x03D9 +,0x4002 +,0x4023 +,0x8F3D +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F37 +,0xA203 +,0x0446 +,0x441E +,0xA201 +,0x03D3 +,0x34D9 +,0xA301 +,0x03CA +,0xA31E +,0x044C +,0xA303 +,0x0446 +,0x8D2C +,0xA203 +,0x03D4 +,0x2630 +,0xBC20 +,0x03D2 +,0x8F00 +,0xBC02 +,0x16C7 +,0xA203 +,0x03D2 +,0x26B0 +,0x8F1E +,0xA203 +,0x0444 +,0xA21E +,0x03D3 +,0x34D9 +,0xA31E +,0x03CA +,0xA303 +,0x0444 +,0x8D16 +,0x4661 +,0x044B +,0xBC02 +,0x1787 +,0x8D11 +,0xA200 +,0x03D7 +,0x4010 +,0x4023 +,0xA300 +,0x03CA +,0xA310 +,0x03D1 +,0xBC21 +,0x03D7 +,0x3843 +,0xBC02 +,0x1700 +,0x4683 +,0xA310 +,0x044C +,0xDFC3 +,0xCFF5 +,0xCFC3 +,0x8EC0 +,0xE9FE +,0xA303 +,0x03CD +,0xE902 +,0x8E00 +,0xDFD5 +,0x3E02 +,0xA200 +,0x03E3 +,0x7000 +,0x5FE0 +,0xA301 +,0x03E3 +,0x2600 +,0x8F12 +,0xA200 +,0x03CB +,0x2680 +,0x8F02 +,0xA200 +,0x03CC +,0x2600 +,0x8F02 +,0xA200 +,0x03CD +,0x2681 +,0x8F06 +,0xBC20 +,0x03E5 +,0xBC21 +,0x03D7 +,0xBD04 +,0x1945 +,0xE002 +,0xE482 +,0x3E01 +,0x8C0E +,0xCFE0 +,0xA200 +,0x03CB +,0x2601 +,0x8F02 +,0xBC02 +,0x17B9 +,0x8C04 +,0xCFE0 +,0xBC02 +,0x183D +,0xCFE0 +,0xB000 +,0xFFFF +,0x69A0 +,0x1FE0 +,0x8FEF +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x2048 +,0x8E00 +,0xFA10 +,0x2600 +,0x8F06 +,0xBC20 +,0x2043 +,0xBC22 +,0x2044 +,0x4001 +,0x8EC0 +,0xFB11 +,0xFB51 +,0x8EB8 +,0xA201 +,0x03E1 +,0xBC22 +,0x3079 +,0xFA20 +,0xB030 +,0xFFD8 +,0xB302 +,0x308C +,0xA303 +,0x03EE +,0x8EC0 +,0x1851 +,0xA301 +,0x03E1 +,0xA203 +,0x03E3 +,0x34D9 +,0xA200 +,0x03FD +,0x5FFA +,0xBC3C +,0x03FA +,0x407E +,0xA303 +,0x03E3 +,0x7009 +,0x2461 +,0x6CE4 +,0x3C1E +,0x4003 +,0xA205 +,0x03E4 +,0x19E3 +,0x0C95 +,0x2131 +,0x6555 +,0x2042 +,0x1863 +,0xA300 +,0x03FD +,0x33A0 +,0xB05A +,0x03E6 +,0x1823 +,0x637E +,0x22C0 +,0x2E04 +,0xB5FE +,0x0005 +,0x01C7 +,0x6678 +,0xE6A7 +,0x684C +,0xA2C2 +,0x18E3 +,0x0C0B +,0x2E94 +,0x8EC0 +,0x0097 +,0xE6C2 +,0xA200 +,0x03DB +,0xBC3C +,0x03DC +,0x409E +,0x405A +,0xBC22 +,0x03EA +,0x77FE +,0xAA18 +,0xE05F +,0xBC23 +,0x308C +,0xE51F +,0xBD03 +,0x19C3 +,0x6910 +,0xBC1C +,0xFA65 +,0x8A03 +,0xBBB0 +,0xCA1C +,0x28EC +,0x88C0 +,0x8E00 +,0xE504 +,0x8EC0 +,0xEA18 +,0xA300 +,0x03DB +,0xBC26 +,0x03E2 +,0xA202 +,0x03E9 +,0xE343 +,0x698C +,0x2902 +,0xA203 +,0x03E0 +,0xBC01 +,0x1A6F +,0xA204 +,0x03F6 +,0x69B0 +,0x5FD5 +,0x3883 +,0x8F02 +,0x4004 +,0xA304 +,0x03F6 +,0x3342 +,0x8F68 +,0xBC26 +,0x03F7 +,0x602D +,0x215F +,0x26C0 +,0xE55F +,0x8F61 +,0x6E11 +,0xBCC5 +,0x6CF4 +,0x2341 +,0x4004 +,0x4026 +,0x19B4 +,0x3210 +,0x8F00 +,0x35B1 +,0xBC40 +,0x1102 +,0x3220 +,0x8F00 +,0x35B1 +,0x2663 +,0xA207 +,0x03F1 +,0x8F01 +,0x26E0 +,0x8F09 +,0x2435 +,0x2429 +,0x2412 +,0x20B5 +,0x8F00 +,0x35F9 +,0x2095 +,0x8F00 +,0xB07E +,0xFFFF +,0xA202 +,0x03F2 +,0x3551 +,0xB20A +,0x004C +,0x3844 +,0x8F0B +,0xB23E +,0x0008 +,0x38A7 +,0x4024 +,0x38E2 +,0x8F05 +,0x38E5 +,0x3378 +,0x3882 +,0x8F01 +,0x5FE4 +,0x38E2 +,0x38A2 +,0x00E3 +,0xA305 +,0x03F2 +,0xA307 +,0x03F1 +,0xDFE3 +,0xBC02 +,0x197C +,0xA203 +,0x03F5 +,0xA202 +,0x03F3 +,0x6056 +,0x0FE4 +,0x3491 +,0xB438 +,0x0001 +,0xA305 +,0x03F5 +,0xB204 +,0x0208 +,0x8F14 +,0xA202 +,0x03F5 +,0xA205 +,0x03F4 +,0xB524 +,0x0001 +,0x20AA +,0x401D +,0x8F06 +,0xA202 +,0x03E4 +,0x4024 +,0x0C94 +,0x3883 +,0xA302 +,0x03E4 +,0x4643 +,0xA31D +,0x03F5 +,0xA31D +,0x03F4 +,0x4002 +,0xA303 +,0x03EF +,0xA302 +,0x03F3 +,0xA202 +,0x03EF +,0x2222 +,0x8F09 +,0x3491 +,0x2262 +,0x8F11 +,0xA202 +,0x03E9 +,0x8E00 +,0xE142 +,0xA302 +,0x03F0 +,0x8D0C +,0xA201 +,0x03F0 +,0x7008 +,0x9FE4 +,0xBC02 +,0x197C +,0xA202 +,0x03F4 +,0x6024 +,0x0FE4 +,0xA302 +,0x03F4 +,0xB008 +,0xFFFF +,0x69A0 +,0x0FD5 +,0x8F79 +,0x700F +,0xDFD5 +,0xBC02 +,0x196D +,0xA31F +,0x03F6 +,0xCFD5 +,0x8D73 +,0x7766 +,0xE145 +,0xA202 +,0x03F0 +,0x3822 +,0xBC3D +,0x03F1 +,0x453F +,0xA204 +,0x0442 +,0x69AC +,0x64E5 +,0x6E28 +,0x6A38 +,0x8F02 +,0xA207 +,0x03EE +,0x26F0 +,0x8F15 +,0xE142 +,0xE2C5 +,0x6175 +,0x60C2 +,0x615A +,0xA242 +,0x243F +,0x242D +,0x017D +,0xB05A +,0x0008 +,0xB4DA +,0x0004 +,0x356A +,0xB4DA +,0x0002 +,0x016A +,0x206A +,0x5FE2 +,0x1955 +,0x8C02 +,0xE605 +,0x5FE2 +,0xB006 +,0xFFFF +,0x2680 +,0x8F3F +,0xA203 +,0x0443 +,0x34D9 +,0xA303 +,0x0443 +,0xB236 +,0x00F0 +,0x8F08 +,0xDFC1 +,0xDFF5 +,0xBC24 +,0x041A +,0xBC02 +,0x196D +,0xCFF5 +,0x8C31 +,0xCFC1 +,0xBC24 +,0x041A +,0x4003 +,0x6E38 +,0xE200 +,0x4005 +,0xA071 +,0xC000 +,0xBD27 +,0x1ABA +,0x6659 +,0x6200 +,0xA071 +,0xC000 +,0x1965 +,0xA207 +,0x03EE +,0xB0DA +,0x041A +,0x003D +,0xB450 +,0x0001 +,0xA305 +,0x03EF +,0x26D0 +,0x4685 +,0x4667 +,0x405F +,0x19EF +,0xE71F +,0xA307 +,0x03CD +,0xBC25 +,0x03F0 +,0x8A06 +,0xE703 +,0x8A0A +,0xE683 +,0x8A03 +,0xE682 +,0xBC3F +,0x03FA +,0xA303 +,0x03CC +,0xA31F +,0x03FD +,0xA303 +,0x03CB +,0xA304 +,0x0442 +,0xA301 +,0x03F0 +,0xE9FE +,0xA300 +,0x03E0 +,0xA202 +,0x03E9 +,0x8EC0 +,0x3491 +,0xA302 +,0x03E9 +,0x0000 +,0xE902 +,0xA201 +,0x03DB +,0xDFD5 +,0x6960 +,0x24C0 +,0xBC02 +,0x19AA +,0xBC20 +,0x03EA +,0xA300 +,0x03E9 +,0xBD04 +,0x1AFD +,0xBC02 +,0x19C8 +,0x8E00 +,0x8E00 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0xA200 +,0x0466 +,0x6980 +,0x1FC0 +,0xBC01 +,0x1BB4 +,0xB310 +,0x00FF +,0xBC01 +,0x1BBA +,0xA201 +,0x0468 +,0xA202 +,0x0467 +,0xB034 +,0xFFFF +,0x3310 +,0xBC20 +,0x0450 +,0xBC01 +,0x1BAA +,0x3880 +,0x4021 +,0xE20E +,0xE24F +,0xBC24 +,0x3002 +,0x88D8 +,0xFA94 +,0xBCDB +,0x0000 +,0xBC24 +,0x3009 +,0x2435 +,0xFA94 +,0x2134 +,0x4004 +,0x19CC +,0xA307 +,0x0465 +,0xBC27 +,0x3013 +,0xA305 +,0x0464 +,0xFAF7 +,0x21B7 +,0x198C +,0x26E0 +,0x8F04 +,0xBC26 +,0x2004 +,0x8E00 +,0xFAD6 +,0x2660 +,0x8F03 +,0xA206 +,0x046A +,0x35B1 +,0xA306 +,0x046A +,0xBC27 +,0x3011 +,0xA206 +,0x0469 +,0x35B1 +,0xFAF7 +,0x2037 +,0xA306 +,0x0469 +,0x8F0F +,0xBC26 +,0x3012 +,0xA207 +,0x046A +,0xFAD6 +,0x21BE +,0x8F03 +,0x8E00 +,0x8C04 +,0xA304 +,0x046B +,0xA301 +,0x046B +,0xA304 +,0x046A +,0xA304 +,0x0469 +,0xBC26 +,0x300A +,0x8E00 +,0xFAD6 +,0x212E +,0x0526 +,0x19B5 +,0x202C +,0xBC25 +,0x2017 +,0x1926 +,0x6CA8 +,0x3AB2 +,0xBC25 +,0x3006 +,0x8F02 +,0xA303 +,0x0467 +,0xBC25 +,0x3003 +,0xBC23 +,0x300C +,0x8E00 +,0xFA73 +,0x2013 +,0x8F13 +,0xBC26 +,0x300D +,0x34E9 +,0xFAD6 +,0x2016 +,0x8F0C +,0xBC26 +,0x300E +,0x8E00 +,0xFAD6 +,0x2016 +,0x8F05 +,0xBC26 +,0x300F +,0x8E00 +,0xFAD6 +,0x2016 +,0x8C02 +,0x18DD +,0x34EA +,0x38A3 +,0x2442 +,0xFAB2 +,0x28E2 +,0x88A0 +,0xBC23 +,0x300B +,0xB524 +,0x0006 +,0xFA73 +,0xB424 +,0x0006 +,0x32B0 +,0x8F01 +,0x4003 +,0x049A +,0xBC23 +,0x2020 +,0xB524 +,0x0001 +,0xFA73 +,0x0859 +,0x2690 +,0xBC23 +,0x2003 +,0x8F02 +,0x4001 +,0x8C0C +,0xFB71 +,0x3451 +,0x8C09 +,0x7000 +,0x7B71 +,0xB012 +,0xFFFF +,0xA301 +,0x0468 +,0xA303 +,0x0467 +,0x4001 +,0xE401 +,0xE441 +,0x8D06 +,0xBC20 +,0x2003 +,0x5FC1 +,0xFA12 +,0x0851 +,0xFB11 +,0xCFC0 +,0x3401 +,0xE9FE +,0xBC21 +,0x00FF +,0x8EC0 +,0x0801 +,0xA300 +,0x0466 +,0xE904 +,0xBC21 +,0x2016 +,0x6E05 +,0x1FD5 +,0xB000 +,0xFFFD +,0xBC22 +,0x3000 +,0xFA31 +,0x7000 +,0x6441 +,0xFA52 +,0xBC23 +,0x044D +,0xBC24 +,0x044F +,0xBC02 +,0x1E36 +,0xA200 +,0x044F +,0x7003 +,0x0FD5 +,0xBC22 +,0x4444 +,0x6915 +,0xE9FC +,0x2456 +,0x28C2 +,0xBC20 +,0x3001 +,0x8890 +,0xBC22 +,0x0450 +,0x6910 +,0xBA10 +,0x28C8 +,0x6E00 +,0xBC41 +,0x88B4 +,0x7101 +,0x2145 +,0x24A9 +,0x28DC +,0x2444 +,0x8EC0 +,0xE54F +,0xE44E +,0xBC21 +,0x3033 +,0xBC22 +,0x201E +,0xB580 +,0x0001 +,0xFA31 +,0x4043 +,0xFA54 +,0x0923 +,0xB012 +,0xFFFF +,0x2220 +,0x8F01 +,0x3310 +,0x8FF7 +,0x8EB8 +,0xA200 +,0x0470 +,0x3280 +,0xBC21 +,0x0477 +,0xBC22 +,0x0474 +,0x184A +,0xA202 +,0x046D +,0xBC40 +,0x1083 +,0x6CE8 +,0xE084 +,0x66B7 +,0x20C1 +,0x8F04 +,0xB044 +,0x3014 +,0x8E00 +,0xFA94 +,0x211C +,0x8F0B +,0x32A0 +,0xB044 +,0xFFFF +,0x8F07 +,0xB058 +,0x3017 +,0x8E00 +,0xFAB5 +,0x219D +,0x8F02 +,0x3844 +,0x8D01 +,0x3491 +,0xB034 +,0x301A +,0xA302 +,0x046D +,0xFA73 +,0xBC22 +,0x3023 +,0x1A59 +,0x2419 +,0xFA52 +,0x211A +,0x8F05 +,0x3300 +,0x8F02 +,0xBC20 +,0x301F +,0x8C05 +,0xFA10 +,0xBC20 +,0x301E +,0x8E00 +,0xFA10 +,0x4202 +,0x0490 +,0xA203 +,0x0473 +,0x2442 +,0x28DA +,0x28C8 +,0x8884 +,0xBC21 +,0x0200 +,0xBC90 +,0x4000 +,0xBC22 +,0x0800 +,0xBC80 +,0x8000 +,0xBC22 +,0x3024 +,0x2690 +,0x4004 +,0xA203 +,0x0454 +,0x1820 +,0xFA52 +,0x0E4B +,0x210A +,0xA300 +,0x0473 +,0x8F04 +,0xBC20 +,0x3025 +,0x8E00 +,0xFA10 +,0x2008 +,0x1881 +,0x8EC0 +,0xA302 +,0x0454 +,0x8E00 +,0xBC20 +,0x200F +,0xA201 +,0x046E +,0xFA10 +,0x2680 +,0x8F00 +,0x3449 +,0x2682 +,0x4000 +,0x8F00 +,0xB012 +,0xFFFF +,0x3210 +,0x8F02 +,0x3317 +,0x40E0 +,0x1801 +,0x8EC0 +,0xA300 +,0x046E +,0x8E00 +,0xBC20 +,0x3031 +,0xBC21 +,0x2000 +,0xFA12 +,0x0811 +,0x2241 +,0xA200 +,0x046E +,0x8F03 +,0x4E00 +,0x0810 +,0xB400 +,0x0004 +,0xB010 +,0x3026 +,0xA203 +,0x0454 +,0xFA31 +,0xBC24 +,0x1000 +,0x0994 +,0x1AD9 +,0x2274 +,0x34D9 +,0x4025 +,0x111D +,0x8F01 +,0x41E3 +,0x0913 +,0x4002 +,0x3240 +,0x3862 +,0x8F02 +,0x4103 +,0x2123 +,0x18DC +,0xB5C6 +,0x0001 +,0xBC26 +,0x302E +,0x0E4C +,0x6980 +,0x3AD6 +,0xBC24 +,0x200B +,0xB5F0 +,0x0004 +,0xA303 +,0x046F +,0x1895 +,0x0E4E +,0xA300 +,0x046E +,0x00FB +,0x6988 +,0x3B91 +,0x8F01 +,0x2681 +,0x8F00 +,0x4002 +,0x2620 +,0x8F01 +,0x2682 +,0x8F00 +,0x4002 +,0x2620 +,0x8F01 +,0x2683 +,0x8F00 +,0x4002 +,0x2620 +,0x8F40 +,0x2604 +,0x8F3E +,0x2620 +,0x8F01 +,0x2685 +,0x8F00 +,0x4002 +,0x2620 +,0x8F33 +,0x2606 +,0x8F31 +,0x2620 +,0x8F01 +,0x2687 +,0x8F33 +,0xBC20 +,0x2005 +,0xBC21 +,0x0200 +,0xFA10 +,0x0801 +,0x2680 +,0x8F20 +,0xA200 +,0x0452 +,0x2602 +,0x8F11 +,0x2603 +,0x8F03 +,0x4060 +,0x8C25 +,0xA300 +,0x0452 +,0xBC20 +,0x3036 +,0xBC21 +,0x2081 +,0xFA10 +,0xFA31 +,0x2088 +,0x4040 +,0x8F18 +,0xA300 +,0x0452 +,0x8D17 +,0xBC20 +,0x3037 +,0xBC21 +,0x2081 +,0xFA10 +,0xFA31 +,0x2188 +,0x4060 +,0x8F0C +,0xA300 +,0x0452 +,0x8D0B +,0x4060 +,0xA300 +,0x0452 +,0x8D07 +,0x4020 +,0x8C05 +,0xA300 +,0x0452 +,0x4000 +,0xA300 +,0x0452 +,0xA200 +,0x0452 +,0xB000 +,0x3039 +,0xBC21 +,0x2006 +,0xFA10 +,0x8EC0 +,0x0003 +,0xFB30 +,0xA200 +,0x0474 +,0xA201 +,0x0453 +,0xB500 +,0x0007 +,0xBC22 +,0x302F +,0x1AC8 +,0x241B +,0xFA52 +,0x211A +,0x8F02 +,0xBC22 +,0x3021 +,0x8C05 +,0xFA52 +,0xBC22 +,0x3020 +,0x8E00 +,0xFA52 +,0xA204 +,0x046C +,0xBC23 +,0x8000 +,0x04DA +,0x3340 +,0x2457 +,0x2456 +,0x8F04 +,0x2454 +,0x28CB +,0x28C2 +,0x8C03 +,0x8880 +,0xA30E +,0x046C +,0xBC21 +,0x3030 +,0xBC22 +,0x3032 +,0xA300 +,0x0453 +,0xFA31 +,0xFA52 +,0xBC23 +,0x1000 +,0x0913 +,0x1A08 +,0xBC25 +,0x0400 +,0x2263 +,0xBC81 +,0x4000 +,0x8F01 +,0xBC20 +,0x0FFF +,0x0810 +,0xBC21 +,0x200C +,0x8EC0 +,0x8E00 +,0xFB30 +,0x0000 +,0xBC20 +,0x3022 +,0xBC21 +,0x3038 +,0x7017 +,0xBA10 +,0x700C +,0x3A31 +,0xA310 +,0x046C +,0xA31E +,0x0470 +,0xA300 +,0x0454 +,0xA301 +,0x0452 +,0x6EE5 +,0x6800 +,0xBD0F +,0x1D81 +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0301 +,0x7008 +,0x3B30 +,0xBC02 +,0x1BF3 +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0201 +,0x7000 +,0x3B30 +,0xBC02 +,0x1BF3 +,0x8E00 +,0x8E00 +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0301 +,0x7008 +,0x3B30 +,0xBC02 +,0x1BF3 +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xA201 +,0x046E +,0xBC20 +,0x3034 +,0xB012 +,0x3026 +,0x6EAF +,0x3A10 +,0xBC22 +,0x3035 +,0xBC23 +,0x2005 +,0xFA31 +,0xB000 +,0x0201 +,0xFA52 +,0xA301 +,0x0454 +,0xFB70 +,0xBC24 +,0x2009 +,0x8EC0 +,0x7008 +,0x3B72 +,0xFB90 +,0xE902 +,0xA200 +,0x0470 +,0x6CC0 +,0x1FD5 +,0x8F34 +,0xA200 +,0x0472 +,0xA201 +,0x0471 +,0x2680 +,0x8F0F +,0xB312 +,0x007F +,0xBC20 +,0x3035 +,0x8F07 +,0xFA10 +,0xB000 +,0x0101 +,0xBC21 +,0x2005 +,0x8C03 +,0x7008 +,0x3B30 +,0x4020 +,0x8C1E +,0xA300 +,0x0472 +,0xB232 +,0x007F +,0x4000 +,0x8F00 +,0x3409 +,0x3300 +,0xA300 +,0x0471 +,0x8F0A +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xBC20 +,0x3035 +,0xBC21 +,0x2005 +,0xFA10 +,0x8C07 +,0x7000 +,0x3B30 +,0xBC02 +,0x1C04 +,0xBC02 +,0x1C7B +,0x4000 +,0xA300 +,0x0472 +,0xBC02 +,0x1D12 +,0x8D13 +,0xBC02 +,0x1C04 +,0xBC02 +,0x1C7B +,0xA200 +,0x0470 +,0xB000 +,0xFFFF +,0xA201 +,0x0471 +,0xA300 +,0x0470 +,0xB232 +,0x007F +,0x4000 +,0x8F00 +,0x3409 +,0xA300 +,0x0471 +,0x7008 +,0x4FD5 +,0xBC20 +,0x2009 +,0x8EC0 +,0xE9FE +,0xFB11 +,0xBC21 +,0x2010 +,0xE908 +,0xBC20 +,0x200E +,0xFA31 +,0xFA12 +,0xBC24 +,0x7F00 +,0x6E1D +,0x1F95 +,0xB036 +,0xFFF9 +,0x0894 +,0xB444 +,0x0008 +,0x6E10 +,0xE581 +,0xFA10 +,0x73F8 +,0x65C4 +,0x0801 +,0xBC21 +,0x0474 +,0xBC40 +,0x1500 +,0xDFA1 +,0xBD03 +,0x1E2E +,0xE0DC +,0xE101 +,0xDFC2 +,0xDFFC +,0xBC02 +,0x1E46 +,0xCFE1 +,0x63A0 +,0x4FA1 +,0x6D34 +,0x4FC2 +,0x6E20 +,0x6480 +,0xB406 +,0x0001 +,0xBC40 +,0x1E00 +,0xDFA1 +,0x7000 +,0x0F95 +,0xBC21 +,0x2009 +,0x8EC0 +,0xE9F8 +,0xFB30 +,0xE040 +,0x6C00 +,0x6246 +,0x6E08 +,0xE185 +,0x6681 +,0xA1C6 +,0x24B5 +,0x28C2 +,0x2444 +,0x8E00 +,0xE5CF +,0x88B8 +,0x8EC0 +,0xE4CE +,0xE643 +,0x3291 +,0x8F0C +,0x24C1 +,0x1448 +,0x41A2 +,0x2442 +,0x4403 +,0x0410 +,0x28CB +,0xB580 +,0x0004 +,0x8890 +,0x8EC0 +,0x0001 +,0x8E00 +,0x8EC0 +,0x4000 +,0x8E00 +,0xBC20 +,0x2092 +,0x4041 +,0xFA10 +,0xBC22 +,0x2093 +,0x0841 +,0x6984 +,0xBA51 +,0x8F0F +,0x4022 +,0x0802 +,0x2681 +,0x8F17 +,0xBC20 +,0x2000 +,0x21C8 +,0xBC20 +,0x2095 +,0x8F02 +,0x8EC0 +,0xE0C1 +,0xFB11 +,0xFA31 +,0xFB11 +,0x8EB8 +,0xBC20 +,0x2094 +,0xBC22 +,0x2000 +,0x6872 +,0xBA10 +,0x8F02 +,0x8EC0 +,0xE4C0 +,0x8E00 +,0x8EC0 +,0xFB30 +,0x8E00 +,0x8EB8 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; +#endif + +const unsigned short bin_patch_E1[] = { +0x2000 +,0x21FF +,0xBC24 +,0x20A0 +,0x8E00 +,0xFA95 +,0xB30A +,0x06AF +,0x8F2E +,0xB30A +,0x08E5 +,0x8F07 +,0xBC25 +,0x08E5 +,0xFB95 +,0xBC22 +,0x399E +,0xBC23 +,0x199E +,0xBC00 +,0x0841 +,0xBC25 +,0x06AF +,0xFB95 +,0x5400 +,0xBC21 +,0xD0B1 +,0xBC02 +,0x07CA +,0x5500 +,0xBC21 +,0x07C2 +,0xBC02 +,0x07CA +,0x40A0 +,0xBC21 +,0x0359 +,0xBC02 +,0x07CA +,0x41A0 +,0xBC21 +,0x00A0 +,0xBC02 +,0x07CA +,0x41C0 +,0xBC21 +,0x4208 +,0xBC02 +,0x07CA +,0x4380 +,0xBC21 +,0x2800 +,0xBC02 +,0x07CA +,0x4E04 +,0xBC00 +,0x08E6 +,0x4344 +,0xBC25 +,0x0400 +,0x2620 +,0x8F06 +,0xBC02 +,0x07F0 +,0x5404 +,0x4025 +,0xBC02 +,0x07FB +,0xBC00 +,0x06C1 +,0xBC02 +,0x07FB +,0x5404 +,0x4025 +,0xBC02 +,0x07F0 +,0xBC00 +,0x06C1 +,0xBDC8 +,0x404E +,0x8E00 +,0xFA11 +,0xBC00 +,0x0630 +,0x8E00 +,0x8E00 +,0x8E00 +,0xBC21 +,0x0002 +,0xBC20 +,0x2008 +,0xBC00 +,0x01BB +,0xBC21 +,0x033F +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7010 +,0x4FF5 +,0xBC22 +,0x201A +,0xBC00 +,0x0161 +,0x4044 +,0xBC25 +,0x1000 +,0xBC02 +,0x07F0 +,0x4E24 +,0xBC00 +,0x0705 +,0xBC22 +,0x399E +,0xBC23 +,0x199E +,0xBC00 +,0x078A +,0xBC24 +,0x2080 +,0x6C88 +,0x3A10 +,0xFA94 +,0xB548 +,0x0005 +,0xBC00 +,0x0E9F +,0xE902 +,0xBC26 +,0x2023 +,0xDFE4 +,0xBC24 +,0x2000 +,0xFAD6 +,0x0934 +,0x26C0 +,0x8F01 +,0xBC26 +,0x3056 +,0x8D02 +,0xBC26 +,0x31F9 +,0xCFE4 +,0xE9FE +,0xBC00 +,0x0FED +,0xBC20 +,0x2090 +,0xBC21 +,0x0100 +,0xFA12 +,0xE902 +,0x0851 +,0x6984 +,0x1FD5 +,0x8F37 +,0x8E00 +,0x8D03 +,0x8E00 +,0xBC20 +,0x2090 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x2600 +,0x8FF5 +,0xBC20 +,0x2090 +,0xBC21 +,0x2091 +,0x714F +,0xBA10 +,0xBC22 +,0x666D +,0x7028 +,0xBB32 +,0x71F8 +,0xBB32 +,0xA203 +,0x0457 +,0x0802 +,0xA204 +,0x0458 +,0x6980 +,0x3B33 +,0xFB34 +,0xBC22 +,0x2545 +,0xA31E +,0x0459 +,0xFB32 +,0x8F0C +,0x2601 +,0x4FE1 +,0x8F0D +,0x2602 +,0xBC21 +,0x0380 +,0x8F09 +,0x2683 +,0x4001 +,0x8F05 +,0xBC02 +,0x40E7 +,0x8D04 +,0xBC21 +,0x03FF +,0xA301 +,0x0456 +,0xA301 +,0x0455 +,0xA200 +,0x0458 +,0xA201 +,0x0457 +,0x260F +,0x8F02 +,0x8E00 +,0x8C03 +,0x3401 +,0x3449 +,0x4000 +,0xCFD5 +,0xA300 +,0x0458 +,0x8EC0 +,0xE9FE +,0xA301 +,0x0457 +,0xBC22 +,0x3105 +,0xA200 +,0x0313 +,0x77DE +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2091 +,0xBC3C +,0x02E0 +,0xBC23 +,0x666D +,0x7000 +,0xFB53 +,0x700E +,0xAA18 +,0xBC24 +,0x0B12 +,0xFB54 +,0x6D36 +,0x7C1C +,0x6C8D +,0x7B54 +,0x8FF9 +,0xA203 +,0x0355 +,0xFB53 +,0xA203 +,0x035A +,0xFB53 +,0xA203 +,0x0464 +,0xBC24 +,0x2004 +,0xFB53 +,0xFA94 +,0xA203 +,0x047F +,0xFB54 +,0xFB53 +,0xA204 +,0x0480 +,0xFB54 +,0xA203 +,0x0481 +,0xFB53 +,0xA204 +,0x0361 +,0xA203 +,0x0362 +,0xFB54 +,0xFB53 +,0xBC23 +,0x5A5A +,0xFB53 +,0x8EC0 +,0xBC23 +,0x2545 +,0xFB53 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_patch_E2[] = { +0x2000 +,0x21FF +,0x8E00 +,0x8E00 +,0x8E00 +,0xBC21 +,0x0002 +,0xBC20 +,0x2008 +,0xBC00 +,0x01A9 +,0xBC21 +,0x033F +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7010 +,0x4FF5 +,0xBC22 +,0x201A +,0xBC00 +,0x014F +,0x240C +,0xA301 +,0x047F +,0xA30F +,0x0480 +,0xA30E +,0x0481 +,0xBC00 +,0x1353 +,0x5380 +,0xBC21 +,0xAC40 +,0xBC02 +,0x07EA +,0x4380 +,0xBC21 +,0x2C00 +,0xBC02 +,0x07EA +,0x43A0 +,0xBC21 +,0xFB40 +,0xBC02 +,0x07EA +,0x43C0 +,0xBC21 +,0x0546 +,0xBC02 +,0x07EA +,0x43E0 +,0xBC21 +,0xFB3C +,0xBC02 +,0x07EA +,0x4400 +,0xBC21 +,0x0537 +,0xBC02 +,0x07EA +,0x4E04 +,0xBC00 +,0x092A +,0x4025 +,0xBC21 +,0x2023 +,0xBC22 +,0x0400 +,0xFA31 +,0x084A +,0x2610 +,0x8F01 +,0xBC02 +,0x081B +,0x8D02 +,0xBC02 +,0x0810 +,0x4E24 +,0xBC00 +,0x0722 +,0x4280 +,0xBC02 +,0x07EA +,0xBC22 +,0x8018 +,0xBC23 +,0x8098 +,0xCFE0 +,0x2600 +,0x1853 +,0x42C0 +,0xBC02 +,0x07EA +,0x4240 +,0xBC21 +,0xE400 +,0xBC02 +,0x07EA +,0x4260 +,0xBC21 +,0x0010 +,0xBC02 +,0x07EA +,0x4040 +,0xBC21 +,0x0FFB +,0xBC02 +,0x07EA +,0x4220 +,0xBC21 +,0x2020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07F8 +,0x4220 +,0xBC21 +,0x1020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07F8 +,0x4220 +,0xBC21 +,0x4020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07F8 +,0x4240 +,0xBC21 +,0xE407 +,0xBC02 +,0x07EA +,0x4260 +,0xBC21 +,0x7010 +,0xBC02 +,0x07EA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07F8 +,0x4520 +,0xBC21 +,0x8001 +,0xBC02 +,0x07EA +,0xBC00 +,0x0794 +,0xBC20 +,0x2090 +,0xBC21 +,0x0100 +,0xFA12 +,0xE902 +,0x0851 +,0x6984 +,0x1FD5 +,0x8F37 +,0x8E00 +,0x8D03 +,0x8E00 +,0xBC20 +,0x2090 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x2600 +,0x8FF5 +,0xBC20 +,0x2090 +,0xBC21 +,0x2091 +,0x714F +,0xBA10 +,0xBC22 +,0x666D +,0x7028 +,0xBB32 +,0x71F8 +,0xBB32 +,0xA203 +,0x045B +,0x0802 +,0xA204 +,0x045C +,0x6980 +,0x3B33 +,0xFB34 +,0xBC22 +,0x2545 +,0xA31E +,0x045D +,0xFB32 +,0x8F0C +,0x2601 +,0x4FE1 +,0x8F0D +,0x2602 +,0xBC21 +,0x0380 +,0x8F09 +,0x2683 +,0x4001 +,0x8F05 +,0xBC02 +,0x40F6 +,0x8D04 +,0xBC21 +,0x03FF +,0xA301 +,0x045A +,0xA301 +,0x0459 +,0xA200 +,0x045C +,0xA201 +,0x045B +,0x260F +,0x8F02 +,0x8E00 +,0x8C03 +,0x3401 +,0x3449 +,0x4000 +,0xCFD5 +,0xA300 +,0x045C +,0x8EC0 +,0xE9FE +,0xA301 +,0x045B +,0xBC22 +,0x3105 +,0xA200 +,0x0314 +,0x77DE +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2091 +,0xBC3C +,0x02E1 +,0xBC23 +,0x666D +,0x7000 +,0xFB53 +,0x700E +,0xAA18 +,0xBC24 +,0x0B12 +,0xFB54 +,0x6D36 +,0x7C1C +,0x6C8D +,0x7B54 +,0x8FF9 +,0xA203 +,0x0356 +,0xFB53 +,0xA203 +,0x035D +,0xFB53 +,0xA203 +,0x0468 +,0xBC24 +,0x2004 +,0xFB53 +,0xFA94 +,0xA203 +,0x0483 +,0xFB54 +,0xFB53 +,0xA204 +,0x0484 +,0xFB54 +,0xA203 +,0x0485 +,0xFB53 +,0xA204 +,0x0364 +,0xA203 +,0x0365 +,0xFB54 +,0xFB53 +,0xBC23 +,0x5A5A +,0xFB53 +,0x8EC0 +,0xBC23 +,0x2545 +,0xFB53 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_coeff_E1[] = { +0x0000 +,0x01FF +,0x0400 +,0x0006 +,0x2AAB +,0x0324 +,0x0324 +,0x0324 +,0x010C +,0x010C +,0x010C +,0x1111 +,0x1259 +,0x0001 +,0x005A +,0x0E9B +,0x0FFF +,0x0FFF +,0x0008 +,0x0001 +,0x0001 +,0x0CCD +,0xFFE0 +,0xFFD8 +,0x00FF +,0xFFAC +,0xFFBC +,0xFF00 +,0x0020 +,0x0048 +,0x0050 +,0x0050 +,0x000E +,0x0002 +,0x7000 +,0x0800 +,0xFFF8 +,0x0008 +,0x002B +,0xFFF6 +,0xFFF8 +,0xFFFE +,0x0003 +,0x0008 +,0x000D +,0x000F +,0x0014 +,0x0019 +,0x0000 +,0x0800 +,0x6580 +,0x0000 +,0x0000 +,0x7FFF +,0x0008 +,0x0078 +,0xFEF5 +,0xFEE8 +,0x0003 +,0x0080 +,0x0080 +,0x0080 +,0x0300 +,0x0006 +,0xC080 +,0xF000 +,0x0660 +,0xDA80 +,0x0000 +,0x0001 +,0x0001 +,0xFFE4 +,0xFFE8 +,0x0080 +,0x0034 +,0x0001 +,0xFFFF +,0x0001 +,0xFFFE +,0x3AC0 +,0x3340 +,0x2BC0 +,0x07C0 +,0x05C0 +,0x03E0 +,0x0008 +,0x1000 +,0x2000 +,0xFF01 +,0xFFE5 +,0xFFE9 +,0x0DA8 +,0x000E +,0xF75E +,0x1136 +,0xEC7B +,0x0D3C +,0xFA9A +,0xFC47 +,0xF58B +,0x1055 +,0x3DDA +,0x3DDA +,0x1055 +,0xF58B +,0xFC47 +,0x1B17 +,0x362A +,0x1B17 +,0x67DA +,0xA798 +,0xFDA6 +,0xF8BE +,0xF36E +,0xF0D4 +,0xF368 +,0xFB18 +,0x04E8 +,0x0C98 +,0x0F2C +,0x0C92 +,0x0742 +,0x025A +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x712C +,0xF1A8 +,0xF9D4 +,0x208E +,0x4BC2 +,0xF280 +,0xF280 +,0x4BC2 +,0x208E +,0xF9D4 +,0xF1A8 +,0x712C +,0x0000 +,0x0200 +,0x0100 +,0x0080 +,0x0040 +,0x0020 +,0x0010 +,0x0008 +,0x0004 +,0x0002 +,0x0001 +,0x02DC +,0x016E +,0x00B7 +,0x0287 +,0x039F +,0x0313 +,0x0355 +,0x0376 +,0x01BB +,0x0201 +,0x03DC +,0x01EE +,0x00F7 +,0x02A7 +,0x038F +,0x031B +,0x00FC +,0x00FC +,0x0198 +,0x0198 +,0x0168 +,0x0350 +,0x01B4 +,0x01B4 +,0x0089 +,0x002C +,0x0058 +,0x002C +,0x0400 +,0x0000 +,0x0003 +,0xFAED +,0xFED0 +,0x09E2 +,0x166A +,0x1BEF +,0x166A +,0x09E2 +,0xFED0 +,0xFAED +,0x2715 +,0x58EB +,0x58EB +,0x2715 +,0xFF8F +,0xFF25 +,0xFEA1 +,0xFE12 +,0xFD8A +,0xFD26 +,0xFD04 +,0xFD43 +,0xFE00 +,0xFF4E +,0x0139 +,0x03B9 +,0x06BB +,0x0A1A +,0x0DA5 +,0x111F +,0x144B +,0x16EC +,0x18CC +,0x19C7 +,0x19C7 +,0x18CC +,0x16EC +,0x144B +,0x111F +,0x0DA5 +,0x0A1A +,0x06BB +,0x03B9 +,0x0139 +,0xFF4E +,0xFE00 +,0xFD43 +,0xFD04 +,0xFD26 +,0xFD8A +,0xFE12 +,0xFEA1 +,0xFF25 +,0xFF8F +,0x0002 +,0x0004 +,0x47B3 +,0xBAC5 +,0x0B85 +,0x0005 +,0x299A +,0x0004 +,0x000A +,0x0660 +,0x0CCD +,0x0003 +,0x0006 +,0x0080 +,0x002C +,0x0020 +,0x0027 +,0xFF4F +,0xFDB1 +,0xFE2E +,0x0465 +,0x0EF1 +,0x161E +,0x1382 +,0x0983 +,0x007B +,0xFD66 +,0xFE7D +,0xFFE2 +,0x0031 +,0x000D +,0x4000 +,0xFD24 +,0x513A +,0xCAEC +,0x3514 +,0xAEC6 +,0x02DC +,0x4000 +,0xEFB5 +,0x6EAE +,0x8DAB +,0x7255 +,0x9152 +,0x104B +,0x2518 +,0x1FBB +,0x14A2 +,0x0D6A +,0x08B9 +,0x05AC +,0x03B0 +,0x0266 +,0x018F +,0x0104 +,0x00A9 +,0x006E +,0x0047 +,0x0001 +,0x0164 +,0x019A +,0x0001 +,0x0002 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0100 +,0xF500 +,0x1C00 +,0x5A00 +,0x0100 +,0xFF00 +,0xF800 +,0x2000 +,0x4F00 +,0x0100 +,0xFE00 +,0xFC00 +,0x2200 +,0x4700 +,0x0000 +,0xFD00 +,0x0100 +,0x2300 +,0x3D00 +,0xFF00 +,0xFE00 +,0x0500 +,0x2200 +,0x3600 +,0xFF00 +,0xFF00 +,0x0900 +,0x2100 +,0x2F00 +,0x0000 +,0x0100 +,0x0C00 +,0x1F00 +,0x2900 +,0x0000 +,0x0300 +,0x0E00 +,0x1D00 +,0x2500 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0004 +,0x0008 +,0x0308 +,0x0312 +,0x01CC +,0x017C +,0x0019 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xE000 +,0x1840 +,0xC880 +,0xFFEE +,0x0000 +,0x4000 +,0x2680 +,0xFF81 +,0xE000 +,0x5000 +,0xD080 +,0xFFB3 +,0xF800 +,0x4500 +,0xD380 +,0xFFE2 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0F80 +,0xDB80 +,0x21C0 +,0xFFCC +,0x0000 +,0xC680 +,0x0540 +,0x0023 +,0x33C0 +,0xDAC0 +,0x5900 +,0xFFDA +,0x0AC0 +,0xDF80 +,0x1940 +,0xFFF7 +,0x7FFF +,0x50C3 +,0x47FA +,0x4026 +,0x392C +,0x32F5 +,0x2D6A +,0x287A +,0x2413 +,0x2027 +,0x1CA8 +,0x198A +,0x16C3 +,0x1449 +,0x1214 +,0x101D +,0x0E5D +,0x0CCD +,0x0B68 +,0x0A2B +,0x0910 +,0x0813 +,0x0015 +,0x0002 +,0x0080 +,0x2848 +,0x051F +,0x0001 +,0x0010 +,0xFC40 +,0xFC40 +,0xFD94 +,0xFD80 +,0xFE80 +,0xFE80 +,0xFE7C +,0xFE7F +,0x02F4 +,0x0001 +,0x0080 +,0x0080 +,0x1000 +,0x0080 +,0x1000 +,0x1000 +,0x0400 +,0x599A +,0x199A +,0x0666 +,0x0021 +,0x2000 +,0x2000 +,0x2000 +,0xFFE4 +,0x0032 +,0x000A +,0x2000 +,0x4000 +,0x0800 +,0x0400 +,0x000C +,0x0005 +,0x000C +,0x00FF +,0x083D +,0x4000 +,0x062F +,0x404C +,0x01B9 +,0x4052 +,0x0155 +,0x405B +,0x0704 +,0x4069 +,0x0786 +,0x4071 +,0x0E9A +,0x4077 +,0x0FEB +,0x4080 +,0x0000 +,0x0000 +,0xFFD5 +,0x0001 +,0x0375 +,0x001E +,0x0AAB +,0x2000 +,0x2AAB +,0x0040 +,0x0005 +,0x001E +,0x4093 +,0xFEE0 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_coeff_E2[] = { +0x0000 +,0x01FF +,0x0400 +,0x0006 +,0x2AAB +,0x0324 +,0x0324 +,0x0324 +,0x010C +,0x010C +,0x010C +,0x1111 +,0x1259 +,0x0001 +,0x005A +,0x0E9B +,0x0FFF +,0x0FFF +,0x0020 +,0x0001 +,0x0001 +,0x0CCD +,0xFFE0 +,0xFFD8 +,0x00FF +,0xFFAC +,0xFFBC +,0xFF00 +,0x0020 +,0x0048 +,0x0050 +,0x0050 +,0x000E +,0x0002 +,0x7000 +,0x0800 +,0xFFF8 +,0x0008 +,0x002B +,0xFFF6 +,0xFFF8 +,0xFFFE +,0x0003 +,0x0008 +,0x000D +,0x000F +,0x0014 +,0x0019 +,0x0000 +,0x0800 +,0x6580 +,0x0000 +,0x0000 +,0x7FFF +,0x0008 +,0x0078 +,0xFEF5 +,0xFEE8 +,0x0003 +,0x0080 +,0x0080 +,0x0080 +,0x0300 +,0x0006 +,0xC080 +,0xF000 +,0x0660 +,0xDA80 +,0x0000 +,0x0001 +,0x0001 +,0xFFE4 +,0xFFE8 +,0x0080 +,0x0034 +,0x0001 +,0xFFFF +,0x0001 +,0xFFFE +,0x3AC0 +,0x3340 +,0x2BC0 +,0x07C0 +,0x05C0 +,0x03E0 +,0x0008 +,0x1000 +,0x2000 +,0xFF01 +,0xFFE5 +,0xFFE9 +,0x0DA8 +,0x000E +,0xF75E +,0x1136 +,0xEC7B +,0x0D3C +,0xFA9A +,0xFC47 +,0xF58B +,0x1055 +,0x3DDA +,0x3DDA +,0x1055 +,0xF58B +,0xFC47 +,0x1B17 +,0x362A +,0x1B17 +,0x67DA +,0xA798 +,0xFDA6 +,0xF8BE +,0xF36E +,0xF0D4 +,0xF368 +,0xFB18 +,0x04E8 +,0x0C98 +,0x0F2C +,0x0C92 +,0x0742 +,0x025A +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x712C +,0xF1A8 +,0xF9D4 +,0x208E +,0x4BC2 +,0xF280 +,0xF280 +,0x4BC2 +,0x208E +,0xF9D4 +,0xF1A8 +,0x712C +,0x0000 +,0x0200 +,0x0100 +,0x0080 +,0x0040 +,0x0020 +,0x0010 +,0x0008 +,0x0004 +,0x0002 +,0x0001 +,0x02DC +,0x016E +,0x00B7 +,0x0287 +,0x039F +,0x0313 +,0x0355 +,0x0376 +,0x01BB +,0x0201 +,0x03DC +,0x01EE +,0x00F7 +,0x02A7 +,0x038F +,0x031B +,0x00FC +,0x00FC +,0x0198 +,0x0198 +,0x0168 +,0x0350 +,0x01B4 +,0x01B4 +,0x0089 +,0x002C +,0x0058 +,0x002C +,0x0400 +,0x0000 +,0x0003 +,0xFAED +,0xFED0 +,0x09E2 +,0x166A +,0x1BEF +,0x166A +,0x09E2 +,0xFED0 +,0xFAED +,0x2715 +,0x58EB +,0x58EB +,0x2715 +,0xFF8F +,0xFF25 +,0xFEA1 +,0xFE12 +,0xFD8A +,0xFD26 +,0xFD04 +,0xFD43 +,0xFE00 +,0xFF4E +,0x0139 +,0x03B9 +,0x06BB +,0x0A1A +,0x0DA5 +,0x111F +,0x144B +,0x16EC +,0x18CC +,0x19C7 +,0x19C7 +,0x18CC +,0x16EC +,0x144B +,0x111F +,0x0DA5 +,0x0A1A +,0x06BB +,0x03B9 +,0x0139 +,0xFF4E +,0xFE00 +,0xFD43 +,0xFD04 +,0xFD26 +,0xFD8A +,0xFE12 +,0xFEA1 +,0xFF25 +,0xFF8F +,0x0002 +,0x0004 +,0x47B3 +,0xBAC5 +,0x0B85 +,0x0005 +,0x299A +,0x0004 +,0x000A +,0x0660 +,0x0CCD +,0x0003 +,0x0006 +,0x0080 +,0x002C +,0x0020 +,0x0027 +,0xFF4F +,0xFDB1 +,0xFE2E +,0x0465 +,0x0EF1 +,0x161E +,0x1382 +,0x0983 +,0x007B +,0xFD66 +,0xFE7D +,0xFFE2 +,0x0031 +,0x000D +,0x4000 +,0xFD24 +,0x513A +,0xCAEC +,0x3514 +,0xAEC6 +,0x02DC +,0x4000 +,0xEFB5 +,0x6EAE +,0x8DAB +,0x7255 +,0x9152 +,0x104B +,0x2518 +,0x1FBB +,0x14A2 +,0x0D6A +,0x08B9 +,0x05AC +,0x03B0 +,0x0266 +,0x018F +,0x0104 +,0x00A9 +,0x006E +,0x0047 +,0x0001 +,0x0164 +,0x019A +,0x0001 +,0x0002 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0100 +,0xF500 +,0x1C00 +,0x5A00 +,0x0100 +,0xFF00 +,0xF800 +,0x2000 +,0x4F00 +,0x0100 +,0xFE00 +,0xFC00 +,0x2200 +,0x4700 +,0x0000 +,0xFD00 +,0x0100 +,0x2300 +,0x3D00 +,0xFF00 +,0xFE00 +,0x0500 +,0x2200 +,0x3600 +,0xFF00 +,0xFF00 +,0x0900 +,0x2100 +,0x2F00 +,0x0000 +,0x0100 +,0x0C00 +,0x1F00 +,0x2900 +,0x0000 +,0x0300 +,0x0E00 +,0x1D00 +,0x2500 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0004 +,0x0008 +,0x0308 +,0x0312 +,0x01CC +,0x017C +,0x0019 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xE000 +,0x1840 +,0xC880 +,0xFFEE +,0x0000 +,0x4000 +,0x2680 +,0xFF81 +,0xE000 +,0x5000 +,0xD080 +,0xFFB3 +,0xF800 +,0x4500 +,0xD380 +,0xFFE2 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0F80 +,0xDB80 +,0x21C0 +,0xFFCC +,0x0000 +,0xC680 +,0x0540 +,0x0023 +,0x33C0 +,0xDAC0 +,0x5900 +,0xFFDA +,0x0AC0 +,0xDF80 +,0x1940 +,0xFFF7 +,0x7FFF +,0x50C3 +,0x47FA +,0x4026 +,0x392C +,0x32F5 +,0x2D6A +,0x287A +,0x2413 +,0x2027 +,0x1CA8 +,0x198A +,0x16C3 +,0x1449 +,0x1214 +,0x101D +,0x0E5D +,0x0CCD +,0x0B68 +,0x0A2B +,0x0910 +,0x0813 +,0x0015 +,0x0002 +,0x0080 +,0x2848 +,0x051F +,0x0001 +,0x0010 +,0xFC40 +,0xFC40 +,0xFD94 +,0xFD80 +,0xFE80 +,0xFE80 +,0xFE7C +,0xFE7F +,0x02F4 +,0x0001 +,0x0080 +,0x0080 +,0x1000 +,0x0080 +,0x1000 +,0x1000 +,0x0400 +,0x599A +,0x199A +,0x0666 +,0x0021 +,0x2000 +,0x2000 +,0x2000 +,0xFFE4 +,0x0032 +,0x000A +,0x2000 +,0x4000 +,0x0800 +,0x0400 +,0x000C +,0x0005 +,0x000C +,0x0038 +,0x01A7 +,0x4000 +,0x0143 +,0x4009 +,0x0000 +,0x0000 +,0x0929 +,0x4020 +,0x0721 +,0x4041 +,0x0755 +,0x4052 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xFFD5 +,0x0001 +,0x0375 +,0x001E +,0x0AAB +,0x2000 +,0x2AAB +,0x0040 +,0x0005 +,0x001E +,0x0001 +,0xFEE0 +,0xFED8 +,0xFED8 +,0x0000 +,0x0040 +,0x40A2 +,0x0000 +}; + +const unsigned short bin_hw_coeff[] = { +0x0000 +,0x0027 +,0xfffd +,0xfffc +,0x0002 +,0x000a +,0x0005 +,0xfff4 +,0xffed +,0x0004 +,0x0024 +,0x0018 +,0xffd8 +,0xffb1 +,0x0006 +,0x00cd +,0x0179 +,0x0001 +,0xfffd +,0x0004 +,0x0000 +,0x000b +,0xffe0 +,0x0047 +,0xff75 +,0x0134 +,0x04c4 +,0xff9c +,0x000f +,0x0007 +,0xfff7 +,0x0006 +,0x0001 +,0x0008 +,0xffdf +,0x005d +,0xff18 +,0x034a +,0xff81 +,0x03d9 +,0x00a6 +,0xfffe +,0x0012 +,0xffa6 +,0x0000 +}; diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h new file mode 100755 index 000000000000..6617cdd49107 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h @@ -0,0 +1,82 @@ +/* mt6628_fm.h + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6626 FM Radio Driver -- head file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MT6626_FM_H__ +#define __MT6626_FM_H__ + +#include "fm_typedef.h" + +//#define FM_PowerOn_with_ShortAntenna +#define MT6626_RSSI_TH_LONG 0xFF01 //FM radio long antenna RSSI threshold(11.375dBuV) +#define MT6626_RSSI_TH_SHORT 0xFEE0 //FM radio short antenna RSSI threshold(-1dBuV) +#define MT6626_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +#define MT6626_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define MT6626_SCAN_CH_SIZE 40 //FM radio scan max channel size +#define MT6626_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +#define MT6626_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) +#define MT6626_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) +#define MT6626_DEEMPHASIS_50us TRUE + +//customer need customize the I2C port +#ifdef MT6516 +#define MT6626_I2C_PORT 2 +#else +#define MT6626_I2C_PORT 0 +#endif + +#define MT6626_SLAVE_ADDR 0xE0 //0x70 7-bit address +#define MT6626_MAX_COUNT 100 +#define MT6626_SCANTBL_SIZE 16 //16*uinit16_t + +#define AFC_ON 0x01 +#if AFC_ON +#define FM_MAIN_CTRL_INIT 0x480 +#else +#define FM_MAIN_CTRL_INIT 0x080 +#endif + +//FM_MAIN_EXTINTRMASK +#define FM_EXT_STC_DONE_MASK 0x01 +#define FM_EXT_RDS_MASK 0x20 + +#define MT6626_FM_STC_DONE_TIMEOUT 12 //second + +//FM_MAIN_CHANDETSTAT +#define FM_MAIN_CHANDET_MASK 0x3FF0 // D4~D13 in address 6FH +#define FM_MAIN_CHANDET_SHIFT 0x04 +#define FM_HOST_CHAN 0x3FF0 + +//FM_MAIN_CFG1(0x36) && FM_MAIN_CFG2(0x37) +#define MT6626_FM_SEEK_UP 0x0 +#define MT6626_FM_SEEK_DOWN 0x01 +#define MT6626_FM_SCAN_UP 0x0 +#define MT6626_FM_SCAN_DOWN 0x01 +#define MT6626_FM_SPACE_INVALID 0x0 +#define MT6626_FM_SPACE_50K 0x01 +#define MT6626_FM_SPACE_100K 0x02 +#define MT6626_FM_SPACE_200K 0x04 + +#define ext_clk //if define ext_clk use external reference clock or mask will use internal +#define MT6626_DEV "MT6626" + +#endif //end of #ifndef __MT6626_FM_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h new file mode 100755 index 000000000000..3e3e4d08eb19 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h @@ -0,0 +1,40 @@ +#ifndef __MT6626_FM_CMD_H__ +#define __MT6626_FM_CMD_H__ + +#include +#include "fm_typedef.h" + +/* FM basic-operation's opcode */ +#define FM_BOP_BASE (0x80) +enum { + FM_WRITE_BASIC_OP = (FM_BOP_BASE + 0x00), + FM_UDELAY_BASIC_OP = (FM_BOP_BASE + 0x01), + FM_RD_UNTIL_BASIC_OP = (FM_BOP_BASE + 0x02), + FM_MODIFY_BASIC_OP = (FM_BOP_BASE + 0x03), + FM_MSLEEP_BASIC_OP = (FM_BOP_BASE + 0x04), + FM_MAX_BASIC_OP = (FM_BOP_BASE + 0x05) +}; + +/* FM BOP's size */ +#define FM_WRITE_BASIC_OP_SIZE (3) +#define FM_UDELAY_BASIC_OP_SIZE (4) +#define FM_RD_UNTIL_BASIC_OP_SIZE (5) +#define FM_MODIFY_BASIC_OP_SIZE (5) +#define FM_MSLEEP_BASIC_OP_SIZE (4) + +fm_s32 mt6626_pwrup_clock_on(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6626_pwrup_digital_init_1(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6626_pwrup_digital_init_2(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6626_pwrdown(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6626_rampdown(fm_u8 *tx_buf, fm_s32 tx_buf_size); +fm_s32 mt6626_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq); +fm_s32 mt6626_seek(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6626_scan(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6626_get_reg(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 addr); +fm_s32 mt6626_set_reg(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 addr, fm_u16 value); +fm_s32 mt6626_patch_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6626_coeff_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6626_hwcoeff_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6626_rom_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h new file mode 100755 index 000000000000..aca40946605b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h @@ -0,0 +1,77 @@ +#ifndef __MT6626_FM_LIB_H__ +#define __MT6626_FM_LIB_H__ + +#include "fm_typedef.h" + +enum { + DSPPATCH = 0xFFF9, + USDELAY = 0xFFFA, + MSDELAY = 0xFFFB, + HW_VER = 0xFFFD, + POLL_N = 0xFFFE, //poling check if bit(n) is '0' + POLL_P = 0xFFFF, //polling check if bit(n) is '1' +}; + +enum { + FM_PUS_DSPPATCH = DSPPATCH, + FM_PUS_USDELAY = USDELAY, + FM_PUS_MSDELAY = MSDELAY, + FM_PUS_HW_VER = HW_VER, + FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0' + FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1' + FM_PUS_MAX +}; + +enum { + DSP_PATH = 0x02, + DSP_COEFF = 0x03, + DSP_HW_COEFF = 0x04 +}; + +enum IMG_TYPE { + IMG_WRONG = 0, + IMG_ROM, + IMG_PATCH, + IMG_COEFFICIENT, + IMG_HW_COEFFICIENT +}; + +enum { + mt6626_E1 = 0, + mt6626_E2 +}; + +enum { + FM_LONG_ANA = 0, + FM_SHORT_ANA +}; + +struct ctrl_word_operation { + fm_u16 addr; + fm_u16 and; + fm_u16 or; +}; + +enum { + MT66x6_BT = 0, + MT66x6_FM, + MT66x6_MAX +}; + +enum { + MT6626_I2S_ON = 0, + MT6626_I2S_OFF +}; + +enum { + MT6626_I2S_MASTER = 0, + MT6626_I2S_SLAVE +}; + +enum { + MT6626_I2S_32K = 0, + MT6626_I2S_44K, + MT6626_I2S_48K +}; + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h new file mode 100755 index 000000000000..4a630f0d3fe9 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h @@ -0,0 +1,68 @@ +/* mt6626_fm_ctrl_link.h + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6626 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MT6626_FM_LINK_H__ +#define __MT6626_FM_LINK_H__ + +#include +#include "fm_link.h" +#include "fm_utils.h" + +#define RX_BUF_SIZE 128 +#define TX_BUF_SIZE 1024 + +#define SW_RETRY_CNT (2) +#define SW_RETRY_CNT_MAX (5) +#define SW_WAIT_TIMEOUT_MAX (100) + +// FM operation timeout define for error handle +#define TEST_TIMEOUT (3) +#define FSPI_EN_TIMEOUT (3) +#define FSPI_MUXSEL_TIMEOUT (3) +#define FSPI_RD_TIMEOUT (3) +#define FSPI_WR_TIMEOUT (3) +#define I2C_RD_TIMEOUT (3) +#define I2C_WR_TIMEOUT (3) +#define EN_TIMEOUT (5) +#define RST_TIMEOUT (3) +#define TUNE_TIMEOUT (3) +#define SEEK_TIMEOUT (10) +#define SCAN_TIMEOUT (15) //usualy scan will cost 10 seconds +#define RDS_RX_EN_TIMEOUT (3) +#define RDS_DATA_TIMEOUT (100) +#define RAMPDOWN_TIMEOUT (3) +#define MCUCLK_TIMEOUT (3) +#define MODEMCLK_TIMEOUT (3) +#define RDS_TX_TIMEOUT (3) +#define PATCH_TIMEOUT (5) +#define COEFF_TIMEOUT (5) +#define HWCOEFF_TIMEOUT (5) +#define ROM_TIMEOUT (5) + +struct fm_link_event { + struct fm_flag_event *ln_event; + struct fm_res_ctx result; // seek/scan/read/RDS +}; + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h new file mode 100755 index 000000000000..4c0b5ad28aab --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h @@ -0,0 +1,84 @@ +#ifndef __MT6626_FM_REG_H__ +#define __MT6626_FM_REG_H__ + +enum MT6626_REG{ + FM_MAIN_CG1_CTRL = 0x60, + FM_MAIN_CG2_CTRL = 0x61, + FM_MAIN_HWVER = 0x62, + FM_MAIN_CTRL = 0x63, + FM_CHANNEL_SET = 0x65, + FM_MAIN_CFG1 = 0x66, + FM_MAIN_CFG2 = 0x67, + FM_MAIN_MCLKDESENSE = 0x38, + FM_MAIN_INTR = 0x69, + FM_MAIN_INTRMASK = 0x6A, + FM_MAIN_EXTINTRMASK = 0x6B, + FM_RSSI_IND = 0x6C, + FM_RSSI_TH = 0x6D, + FM_MAIN_RESET = 0x6E, + FM_MAIN_CHANDETSTAT = 0x6F, + FM_RDS_CFG0 = 0x80, + FM_RDS_INFO = 0x81, + FM_RDS_DATA_REG = 0x82, + FM_RDS_GOODBK_CNT = 0x83, + FM_RDS_BADBK_CNT = 0x84, + FM_RDS_PWDI = 0x85, + FM_RDS_PWDQ = 0x86, + FM_RDS_FIFO_STATUS0 = 0x87, + FM_FT_CON9 = 0x8F, + FM_DSP_PATCH_CTRL = 0x90, + FM_DSP_PATCH_OFFSET = 0x91, + FM_DSP_PATCH_DATA = 0x92, + FM_DSP_MEM_CTRL4 = 0x93, + FM_ADDR_PAMD = 0xB4, + FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6, + FM_RDS_POINTER = 0xF0, +}; + +//RDS_BDGRP_ABD_CTRL_REG +enum{ + BDGRP_ABD_EN = 0x0001, + BER_RUN = 0x2000 +}; +#define FM_DAC_CON1 0x83 +#define FM_DAC_CON2 0x84 +#define FM_FT_CON0 0x86 +enum{ + FT_EN = 0x0001 +}; + +#define FM_I2S_CON0 0x90 +enum{ + I2S_EN = 0x0001, + FORMAT = 0x0002, + WLEN = 0x0004, + I2S_SRC = 0x0008 +}; + +//FM_MAIN_CTRL +enum{ + TUNE = 0x0001, + SEEK = 0x0002, + SCAN = 0x0004, + RDS_MASK = 0x0010, + MUTE = 0x0020, + RDS_BRST = 0x0040, + RAMP_DOWN = 0x0100, +}; + +//FM_MAIN_INTR +enum{ + FM_INTR_STC_DONE = 0x0001, + FM_INTR_IQCAL_DONE = 0x0002, + FM_INTR_DESENSE_HIT = 0x0004, + FM_INTR_CHNL_CHG = 0x0008, + FM_INTR_SW_INTR = 0x0010, + FM_INTR_RDS = 0x0020 +}; + +enum{ + ANTENNA_TYPE = 0x0010, +}; + +#endif //__MT6626_FM_REG_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.c new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h new file mode 100755 index 000000000000..8a94e411c750 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h @@ -0,0 +1,5 @@ +#ifndef __MTK_FM_H__ +#define __MTK_FM_H__ + + +#endif //__MTK_FM_H__ diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c new file mode 100755 index 000000000000..67156d1aa77d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c @@ -0,0 +1,672 @@ +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_rds.h" +#include "fm_cust_cfg.h" + +#include "mt6626_fm_reg.h" +#include "mt6626_fm_link.h" +#include "mt6626_fm.h" +#include "mt6626_fm_cmd.h" + +static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_WRITE_BASIC_OP; + buf[1] = FM_WRITE_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((value) & 0x00FF); + buf[4] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + + return (FM_WRITE_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_UDELAY_BASIC_OP; + buf[1] = FM_UDELAY_BASIC_OP_SIZE; + buf[2] = (fm_u8)((value) & 0x000000FF); + buf[3] = (fm_u8)((value >> 8) & 0x000000FF); + buf[4] = (fm_u8)((value >> 16) & 0x000000FF); + buf[5] = (fm_u8)((value >> 24) & 0x000000FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return (FM_UDELAY_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_RD_UNTIL_BASIC_OP; + buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask) & 0x00FF); + buf[4] = (fm_u8)((mask >> 8) & 0x00FF); + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_RD_UNTIL_BASIC_OP_SIZE + 2); +} + +static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_MODIFY_BASIC_OP; + buf[1] = FM_MODIFY_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask_and) & 0x00FF); + buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF); + buf[5] = (fm_u8)((mask_or) & 0x00FF); + buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_MODIFY_BASIC_OP_SIZE + 2); +} + +#if 0 +static fm_s32 fm_bop_msleep(fm_u32 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_MSLEEP_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_MSLEEP_BASIC_OP; + buf[1] = FM_MSLEEP_BASIC_OP_SIZE; + buf[2] = (fm_u8)((value) & 0x000000FF); + buf[3] = (fm_u8)((value >> 8) & 0x000000FF); + buf[4] = (fm_u8)((value >> 16) & 0x000000FF); + buf[5] = (fm_u8)((value >> 24) & 0x000000FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return (FM_MSLEEP_BASIC_OP_SIZE + 2); +} +#endif + +/* + * mt6626_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6626_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //FM Digital Clock enable + pkt_size += fm_bop_write(0x60, 0x3000, &buf[pkt_size], buf_size - pkt_size);//wr 60 3000 + pkt_size += fm_bop_write(0x60, 0x3001, &buf[pkt_size], buf_size - pkt_size);//wr 60 3001 + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3ms + pkt_size += fm_bop_write(0x60, 0x3003, &buf[pkt_size], buf_size - pkt_size);//wr 60 3003 + pkt_size += fm_bop_write(0x60, 0x3007, &buf[pkt_size], buf_size - pkt_size);//wr 60 3007 + //no low power mode, analog line in, long antenna + pkt_size += fm_bop_modify(0x61, 0xFF63, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_patch_download - Wholechip FM Power Up: step 3, download patch to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6626_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_PATCH_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + +/* + * mt6626_coeff_download - Wholechip FM Power Up: step 3,download coeff to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6626_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_COEFF_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + +/* + * mt6626_hwcoeff_download - Wholechip FM Power Up: step 3,download hwcoeff to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6626_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_HWCOEFF_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + +/* + * mt6626_rom_download - Wholechip FM Power Up: step 3,download rom to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6626_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ROM_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + +/* + * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6626_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon + pkt_size += fm_bop_write(0x6A, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6A 0020 + pkt_size += fm_bop_write(0x6B, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6B 0020 + pkt_size += fm_bop_write(0xA0, 0xD0B1, &buf[pkt_size], buf_size - pkt_size);//wr a0 D0B1 + pkt_size += fm_bop_write(0x60, 0x300F, &buf[pkt_size], buf_size - pkt_size);//wr 60 300F + pkt_size += fm_bop_write(0x61, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 61 3 + pkt_size += fm_bop_write(0x61, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 61 2 + //pkt_size += fm_bop_modify(0x61, 0xFFFF, 0x0002, &buf[pkt_size], buf_size - pkt_size); + //pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6626_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//Poll 64[0~4] = 2 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6626_pwrdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Disable HW clock control + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size);//wr 60 330F + //Reset ASIP + pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 61 0001 + //digital core + digital rgf reset + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + //Disable all clock + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000 + //Reset rgfrf + pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 60 4000 + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6626_rampdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_RAMPDOWN_OPCODE; + pkt_size = 4; + + //Clear DSP state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0 + //Set DSP ramp down state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 1 + //@Wait for STC_DONE interrupt@ + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Clear DSP ramp down state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 0 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +fm_s32 mt6626_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + freq = (freq - 640) * 2; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + //Set desired channel & channel parameter + pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20) + //Enable hardware controlled tuning sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFE, TUNE, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1 + //Wait for STC_DONE interrupt + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_seek - execute seek action, + * @buf - target buf + * @buf_size - buffer size + * @seekdir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6626_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SEEK_OPCODE; + pkt_size = 4; + + //Program seek direction + if (seekdir == 0) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //Program scan channel spacing + if (space == 1) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else if (space == 2) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } else if (space == 4) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100 + } + + //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap + //0x66[9:0] freq upper bound + max_freq = (max_freq - 640) * 2; + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + //0x67[9:0] freq lower bound + min_freq = (min_freq - 640) * 2; + pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //Enable hardware controlled seeking sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SEEK, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + //Wait for STC_DONE interrupt + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/* + * mt6626_scan - execute scan action, + * @buf - target buf + * @buf_size - buffer size + * @scandir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6626_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SCAN_OPCODE; + pkt_size = 4; + + //Program seek direction + if (scandir == 0) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //Program scan channel spacing + if (space == 1) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else if (space == 2) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } else if (space == 4) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100 + } + + //disable wrap , if it is auto scan function, 0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 0, no wrap + //0x66[9:0] freq upper bound + max_freq = (max_freq - 640) * 2; + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + //0x67[9:0] freq lower bound + min_freq = (min_freq - 640) * 2; + pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //Enable hardware controlled scanning sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SCAN, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + //Wait for STC_DONE interrupt + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +fm_s32 mt6626_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_READ_OPCODE; + buf[2] = 0x01; + buf[3] = 0x00; + buf[4] = addr; + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + return 5; +} + +fm_s32 mt6626_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_WRITE_OPCODE; + buf[2] = 0x03; + buf[3] = 0x00; + buf[4] = addr; + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + return 7; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c new file mode 100755 index 000000000000..046519c2a267 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c @@ -0,0 +1,135 @@ +/* mt6626_fm_eint.c + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * mt6626 FM Radio Driver -- EINT functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_eint.h" + +#ifdef MT6516 +#include +#include +#endif +#ifdef MT6573 +#include +#include +#endif +#ifdef MT6575 +#include +#include +#endif + +#include +#include + +struct fm_eint_interface { + void (*mask)(fm_u32 eint_num); + void (*unmask)(fm_u32 eint_num); + void (*set_hw_debounce)(fm_u32 eint_num, fm_u32 ms); + void (*set_polarity)(fm_u32 eint_num, fm_u32 pol); + fm_u32(*set_sens)(fm_u32 eint_num, fm_u32 sens); + void (*registration)(fm_u32 eint_num, fm_u32 is_deb_en, fm_u32 pol, void (EINT_FUNC_PTR)(void), fm_u32 is_auto_umask); + fm_s32(*init)(void); +}; + + +#ifdef MT6516 +extern void MT6516_EINTIRQUnmask(fm_u32 line); +extern void MT6516_EINTIRQMask(fm_u32 line); +extern void MT6516_EINT_Set_HW_Debounce(fm_u8 eintno, fm_u32 ms); +extern fm_u32 MT6516_EINT_Set_Sensitivity(fm_u8 eintno, kal_bool sens); +extern void MT6516_EINT_Registration(fm_u8 eintno, kal_bool Dbounce_En, + kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void), + kal_bool auto_umask); +#endif + +static struct fm_eint_interface fm_eint_ops = { +#ifdef MT6516 + .mask = MT6516_EINTIRQMask, + .unmask = MT6516_EINTIRQUnmask, + .set_hw_debounce = MT6516_EINT_Set_HW_Debounce, + .set_polarity = NULL, + .set_sens = MT6516_EINT_Set_Sensitivity, + .registration = MT6516_EINT_Registration, + .init = NULL, +#else + .mask = mt65xx_eint_mask, + .unmask = mt65xx_eint_unmask, + .set_hw_debounce = mt65xx_eint_set_hw_debounce, + .set_polarity = mt65xx_eint_set_polarity, + .set_sens = mt65xx_eint_set_sens, + .registration = mt65xx_eint_registration, + .init = mt65xx_eint_init, +#endif +}; +fm_s32 fm_enable_eint(void) +{ + WCN_DBG(FM_INF | EINT, "%s\n", __func__); + fm_eint_ops.unmask(CUST_EINT_FM_RDS_NUM); + return 0; +} + +fm_s32 fm_disable_eint(void) +{ + WCN_DBG(FM_INF | EINT, "%s\n", __func__); + fm_eint_ops.mask(CUST_EINT_FM_RDS_NUM); + return 0; +} + +fm_s32 fm_request_eint(void (*parser)(void)) +{ + WCN_DBG(FM_NTC | EINT, "%s\n", __func__); + fm_eint_ops.set_sens(CUST_EINT_FM_RDS_NUM, CUST_EINT_FM_RDS_SENSITIVE); + fm_eint_ops.set_hw_debounce(CUST_EINT_FM_RDS_NUM, CUST_EINT_FM_RDS_DEBOUNCE_CN); + fm_eint_ops.registration(CUST_EINT_FM_RDS_NUM, + CUST_EINT_FM_RDS_DEBOUNCE_EN, + CUST_EINT_FM_RDS_POLARITY, + parser, + 0); + fm_eint_ops.mask(CUST_EINT_FM_RDS_NUM); + return 0; +} + +fm_s32 fm_eint_pin_cfg(fm_s32 mode) +{ + int ret = 0; + + WCN_DBG(FM_NTC | EINT, "%s\n", __func__); + + switch (mode) { + case FM_EINT_PIN_EINT_MODE: + mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_GPIO); + mt_set_gpio_pull_enable(GPIO_FM_RDS_PIN, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO_FM_RDS_PIN, GPIO_PULL_UP); + mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_EINT); + break; + case FM_EINT_PIN_GPIO_MODE: + mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_FM_RDS_PIN, GPIO_DIR_IN); + break; + default: + ret = -1; + break; + } + + return ret; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c new file mode 100755 index 000000000000..2b7c5d4dbc7b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c @@ -0,0 +1,1147 @@ +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_patch.h" +#include "fm_config.h" + +#include "mt6626_fm_reg.h" +#include "mt6626_fm.h" +#include "mt6626_drv_dsp.h" +#include "mt6626_fm_link.h" +#include "mt6626_fm_lib.h" +#include "mt6626_fm_cmd.h" + +#define MT6626_FM_PATCH_PATH "/etc/firmware/mt6626_fm_patch.bin" +#define MT6626_FM_COEFF_PATH "/etc/firmware/mt6626_fm_coeff.bin" +#define MT6626_FM_HWCOEFF_PATH "/etc/firmware/mt6626_fm_hwcoeff.bin" +#define MT6626_FM_ROM_PATH "/etc/firmware/mt6626_fm_rom.bin" + +extern void fm_low_power_wa(int fmon); +extern void mt66x6_poweron(int idx); +extern void mt66x6_poweroff(int idx); + +static struct fm_callback *fm_cb_op; + +/* mt6626 FM Receiver Power Up Sequence*/ +static const struct ctrl_word_operation PowerOnSetting[] = { + //@Wholechip FM Power Up: FM Digital Clock enable + {0x60, 0x0, 0x3000}, + {0x60, 0x0, 0x3001}, + {MSDELAY, 0x0, 0x0003},//Delay 3ms + {0x60, 0x0, 0x3003}, + {0x60, 0x0, 0x3007}, + {HW_VER, 0x99, 0x0000}, + //antenna and audio path config +#ifdef FMRADIO_I2S_SUPPORT +#ifdef FM_PowerOn_with_ShortAntenna + {0x61, 0xFF73, 0x0090},//no low power mode, I2S, short antenna +#else + {0x61, 0xFF73, 0x0080},//no low power mode, I2S, long antenna +#endif + {0x9B, 0xFFF7, 0x0008},//0000->master, 0008->slave + {0x5F, 0xE7FF, 0x0000},//0000->32K, 0800->44.1K, 1000->48K + //{0x61, 0xFF73, 0x0080},//no low power mode, I2S, long antenna, 0xff63 + //{0x9B, 0xFFF7, 0x0008},//0000->master, 0008->slave + //{0x5F, 0xE7FF, 0x0000},//0000->32K, 0800->44.1K, 1000->48K +#else +#ifdef FM_PowerOn_with_ShortAntenna + {0x61, 0xFF63, 0x0010},//no low power mode, analog line in, short antenna +#else + {0x61, 0xFF63, 0x0000},//no low power mode, analog line in, long antenna +#endif +#endif + {HW_VER, 0x0062, 0x0000},//read the HW version + + //@Wholechip FM Power Up: FM Digital Init: download patch/DSP coefficient/HWACC coefficient + {DSPPATCH, 0x0, DSP_PATH}, + {DSPPATCH, 0x0, DSP_COEFF}, + {DSPPATCH, 0x0, DSP_HW_COEFF}, + {0x90, 0x0, 0x0040}, + {0x90, 0x0, 0x0000}, + + //@Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon + {0x6A, 0x0, 0x0020}, + {0x6B, 0x0, 0x0020}, + {0x60, 0x0, 0x300F}, + {0x61, 0xFFFF, 0x0002}, + {0x61, 0xFFFE, 0x0000}, + {POLL_P, 0x64, 0x2} +}; +#define POWER_ON_COMMAND_COUNT (sizeof(PowerOnSetting)/sizeof(PowerOnSetting[0])) + +static int Chip_Version = mt6626_E1; + + +static fm_s32 mt6626_pwron(fm_s32 data) +{ + mt66x6_poweron(MT66x6_FM); + return 0; +} + + +static fm_s32 mt6626_pwroff(fm_s32 data) +{ + mt66x6_poweroff(MT66x6_FM); + return 0; +} + +static fm_s32 Delayms(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data); + msleep(data); + return 0; +} + +static fm_s32 Delayus(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data); + udelay(data); + return 0; +} + +static fm_s32 mt6626_read(fm_u8 addr, fm_u16 *val) +{ + fm_s32 ret = 0; + + ret = fm_ctrl_rx(addr, val); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "rd 0x%02x err\n", addr); + return ret; + } + + WCN_DBG(FM_DBG | CHIP, "rd 0x%02x 0x%04x\n", addr, *val); + return ret; +} + +static fm_s32 mt6626_write(fm_u8 addr, fm_u16 val) +{ + fm_s32 ret = 0; + + ret = fm_ctrl_tx(addr, val); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "wr 0x%02x err\n", addr); + return ret; + } + + WCN_DBG(FM_DBG | CHIP, "wr 0x%02x 0x%04x\n", addr, val); + return ret; +} + +static fm_s32 mt6626_write1(fm_u8 addr, fm_u16 val) +{ + return fm_ctrl_tx(addr, val); +} + +static fm_s32 mt6626_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask) +{ + fm_s32 ret = 0; + fm_u16 val; + + ret = mt6626_read(addr, &val); + + if (ret) + return ret; + + val = ((val & (mask)) | bits); + ret = mt6626_write(addr, val); + + return ret; +} + +static fm_u16 mt6626_get_chipid(void) +{ + return 0x6626; +} + +static void mt6626_TUNE_ON(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "tune on\n"); + mt6626_read(FM_MAIN_CTRL, &dataRead); + //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFE)|TUNE); + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | TUNE); +} + +static void mt6626_SEEK_ON(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "seek on\n"); + mt6626_read(FM_MAIN_CTRL, &dataRead); + //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFD)|SEEK); + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | SEEK); +} + +static void mt6626_SCAN_ON(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "scan on\n"); + mt6626_read(FM_MAIN_CTRL, &dataRead); + //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFB)|SCAN); + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | SCAN); +} + +/* MT6628_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static fm_s32 mt6626_SetAntennaType(fm_s32 type) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + mt6626_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) { + dataRead |= ANTENNA_TYPE; + } else { + dataRead &= (~ANTENNA_TYPE); + } + + mt6626_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static fm_s32 mt6626_GetAntennaType(void) +{ + fm_u16 dataRead; + + mt6626_read(FM_MAIN_CG2_CTRL, &dataRead); + WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long"); + + if (dataRead&ANTENNA_TYPE) + return FM_SHORT_ANA; //short antenna + else + return FM_LONG_ANA; //long antenna +} + +static fm_s32 mt6626_writeFA(fm_u16 *buff, fm_u8 fa) +{ + fm_u8 i = 0; + + for (i = 0; i < 3; i++) { + if ((fa >> i)& 0x1) + *buff |= (1 << (12 + i)); + else + *buff &= ~(1 << (12 + i)); + } + + return 0; +} + +static fm_s32 mt6626_Mute(fm_bool mute) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + mt6626_read(FM_MAIN_CTRL, &dataRead); + + if (mute == 1) { + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020); + } else { + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFDF)); + } + + return 0; +} + +/* + * mt6626_WaitSTCDone - wait for stc done flag change to '1' + * @waittime - the total wait time in ms + * @interval - the delay time of every polling loop in ms + * if success, return 0; else error code + */ +static fm_s32 mt6626_WaitSTCDone(fm_u32 waittime, fm_u32 interval) +{ + fm_u16 dataRead; + fm_s32 cnt; + + if (interval) { + cnt = waittime / interval; + } else { + cnt = 0; + } + + do { + if (cnt-- < 0) { + return -1; //wait for STC done failed + } + + Delayms(interval); + mt6626_read(FM_MAIN_INTR, &dataRead); + } while ((dataRead&FM_INTR_STC_DONE) == 0); + + return 0; +} + +static fm_s32 mt6626_ClearSTCDone(void) +{ + fm_u16 dataRead; + + mt6626_read(FM_MAIN_INTR, &dataRead); + mt6626_write(FM_MAIN_INTR, dataRead | FM_INTR_STC_DONE);//clear status flag + return 0; +} + +static fm_s32 mt6626_RampDown(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + //Clear DSP state + mt6626_read(FM_MAIN_CTRL, &dataRead); + mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF0)); //clear rgf_tune/seek/scan/dsp_init + + //Set DSP ramp down state + mt6626_read(FM_MAIN_CTRL, &dataRead); + mt6626_write(FM_MAIN_CTRL, (dataRead | RAMP_DOWN)); + + //Check STC_DONE status flag (not the interrupt flag!) + if (mt6626_WaitSTCDone(1000, 1)) { + WCN_DBG(FM_ALT | CHIP, "ramp down failed\n"); + return -1; + } + + //Clear DSP ramp down state + mt6626_read(FM_MAIN_CTRL, &dataRead); + mt6626_write(FM_MAIN_CTRL, (dataRead&(~RAMP_DOWN))); + + mt6626_ClearSTCDone(); + return 0; +} + +/* +* mt6626_DspPatch - DSP download procedure +* @img - source dsp bin code +* @type - rom/patch/coefficient/hw_coefficient +* +*/ +static fm_s32 mt6626_DspPatch(const fm_u16 *img, enum IMG_TYPE type) +{ + fm_u32 ctrl_code = 0; + fm_u16 data_len = 0; // in words + fm_u16 i; + + FMR_ASSERT(img); + + WCN_DBG(FM_DBG | CHIP, "down load DSP patch %d (1-rom, 2-patch, 3-coe, 4-hwcoe)\n", type); + + switch (type) { + case IMG_ROM: //rom code + case IMG_PATCH: //patch + ctrl_code = 0x10; + break; + case IMG_COEFFICIENT: //coeff + ctrl_code = 0xe; + break; + case IMG_HW_COEFFICIENT: //HW coeff + ctrl_code = 0xd; + break; + default: + break; + } + + data_len = img[1] - img[0] + 1; + WCN_DBG(FM_DBG | CHIP, "patch len: %d\n", data_len); + + if (!(data_len > 0)) { + ; //error + return -FM_EPARA; + } + + mt6626_write(FM_DSP_PATCH_CTRL, 0); + mt6626_write(FM_DSP_PATCH_OFFSET, img[0]); //Start address + mt6626_write(FM_DSP_PATCH_CTRL, 0x40); //Reset download control + mt6626_write(FM_DSP_PATCH_CTRL, ctrl_code); //Set download control + + switch (type) { + case IMG_ROM: + case IMG_PATCH: + case IMG_HW_COEFFICIENT: + WCN_DBG(FM_DBG | CHIP, "rom/patch/hw_coefficient downloading......\n"); + + for (i = 0; i < data_len; i++) { + mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]); + } + + break; + case IMG_COEFFICIENT: + WCN_DBG(FM_DBG | CHIP, "coefficient downloading......\n"); + + if (MT6626_DEEMPHASIS_50us) { + for (i = 0; i < data_len; i++) { + if (i == 86) { + mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG)); + } else if (i == 292) { + mt6626_write1(FM_DSP_PATCH_DATA, 0x332B); + mt6626_write1(FM_DSP_PATCH_DATA, 0x2545); + mt6626_write1(FM_DSP_PATCH_DATA, 0x1344); + mt6626_write1(FM_DSP_PATCH_DATA, 0x09F5); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0526); + mt6626_write1(FM_DSP_PATCH_DATA, 0x02A9); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0160); + mt6626_write1(FM_DSP_PATCH_DATA, 0x00B6); + mt6626_write1(FM_DSP_PATCH_DATA, 0x005E); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0031); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0000); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0000); + mt6626_write1(FM_DSP_PATCH_DATA, 0x0000); + i += 12; + } else if (i == 505) { + mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT)); + } else { + mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]); + } + } + } else { + for (i = 0; i < data_len; i++) { + if (i == 86) { + mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG)); + } else if (i == 505) { + mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT)); + } else { + mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]); + } + } + } + + break; + default: + break; + } + + WCN_DBG(FM_DBG | CHIP, "down load DSP patch %d ok\n", type); + return 0; +} + +static fm_s32 mt6626_PowerUp(fm_u16 *chip_id, fm_u16 *device_id) +{ + fm_s32 ret = 0; + fm_s32 i; + fm_u16 tmp_reg, cnt = 0; + + const fm_u16 *bin_patch = NULL; + const fm_u16 *bin_coeff = NULL; + + FMR_ASSERT(chip_id); + FMR_ASSERT(device_id); + + WCN_DBG(FM_DBG | CHIP, "pwr on seq\n"); + + // mt6626 FM power on sequence + for (i = 0; i < POWER_ON_COMMAND_COUNT; i++) { + switch (PowerOnSetting[i].addr) { + case FM_PUS_DSPPATCH: + + switch (PowerOnSetting[i].or) { + case DSP_PATH: //DSP path download + mt6626_DspPatch(bin_patch, IMG_PATCH); + break; + case DSP_COEFF: //DSP coefficient download + mt6626_DspPatch(bin_coeff, IMG_COEFFICIENT); + break; + case DSP_HW_COEFF: //DSP HW coefficient download + mt6626_DspPatch(bin_hw_coeff, IMG_HW_COEFFICIENT); + break; + default: + break; + } + + break; + case FM_PUS_POLL_P: + cnt = 0; + + do { + mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg); + tmp_reg &= PowerOnSetting[i].or; + + if (tmp_reg == 0) { + Delayms(10); + cnt++; + } + } while ((tmp_reg == 0) && (cnt < (MT6626_MAX_COUNT << 1))); + + if (cnt == (MT6626_MAX_COUNT << 1)) { + WCN_DBG(FM_ALT | CHIP, "polling status Active failed:0x%02X\n", (fm_u8)PowerOnSetting[i].and); + return -FM_EPARA; + } + + break; + case FM_PUS_POLL_N: + cnt = 0; + + do { + mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg); + tmp_reg &= PowerOnSetting[i].or; + + if (tmp_reg != 0) { + Delayms(10); + cnt++; + } + } while ((tmp_reg != 0) && (cnt < MT6626_MAX_COUNT)); + + if (cnt == MT6626_MAX_COUNT) { + WCN_DBG(FM_ALT | CHIP, "polling status Negative failed:0x%02X\n", (fm_u8)PowerOnSetting[i].and); + return -FM_EPARA; + } + + break; + case FM_PUS_USDELAY: + Delayus(PowerOnSetting[i].or); + break; + case FM_PUS_MSDELAY: + Delayms(PowerOnSetting[i].or); + break; + case FM_PUS_HW_VER: + + switch (PowerOnSetting[i].and) { + case 0x99: + mt6626_read(0x99, &tmp_reg); + + switch (tmp_reg) { + case 0x0: + Chip_Version = mt6626_E1; + bin_patch = bin_patch_E1; + bin_coeff = bin_coeff_E1; + break; + case 0x8A01: + default: + Chip_Version = mt6626_E2; + bin_patch = bin_patch_E2; + bin_coeff = bin_coeff_E2; + break; + } + + break; + case 0x62: + mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg); + //record chip id & device id + *chip_id = tmp_reg; + *device_id = tmp_reg; + WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg); + break; + case 0x1C: + mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg); + + if (PowerOnSetting[i].or) { + mt6626_write(PowerOnSetting[i].and, (tmp_reg | 0x8000)); + } else { + mt6626_write(PowerOnSetting[i].and, (tmp_reg&0x7FFF)); + } + + break; + default: + break; + } + + break; + default: + + if (PowerOnSetting[i].and != 0) { + if (mt6626_read((fm_u8)PowerOnSetting[i].addr, &tmp_reg)) { + WCN_DBG(FM_ALT | CHIP, "power up failed, can't read reg %02X\n", (fm_u8)PowerOnSetting[i].and); + return -FM_EPARA; + } + + tmp_reg &= PowerOnSetting[i].and; + tmp_reg |= PowerOnSetting[i].or; + } else { + tmp_reg = PowerOnSetting[i].or; + } + + if (mt6626_write((fm_u8)PowerOnSetting[i].addr, tmp_reg)) { + WCN_DBG(FM_ALT | CHIP, "power up failed, can't write reg %02X\n", (fm_u8)PowerOnSetting[i].addr); + return -FM_EPARA; + } + + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq done\n"); + return ret; +} + +static fm_s32 mt6626_PowerDown(void) +{ + fm_s32 ret = 0; + fm_s16 i; + fm_u16 dataRead; + + /*SW work around for MCUFA issue. + *if interrupt happen before doing rampdown, DSP can't switch MCUFA back well. + * In case read interrupt, and clean if interrupt found before rampdown. + */ + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + mt6626_read(FM_MAIN_INTR, &dataRead); + + if (dataRead & 0x1) { + mt6626_write(FM_MAIN_INTR, dataRead);//clear status flag + } + + mt6626_RampDown(); + + mt6626_write(0x60, 0x330F); + mt6626_write(FM_MAIN_CG2_CTRL, 1); + + for (i = 0; i < 4; i++) { + mt6626_read(0x6E, &dataRead); + mt6626_write(0x6E, (dataRead&0xFFF8)); + } + + mt6626_write(FM_MAIN_CG1_CTRL, 0); + mt6626_write(FM_MAIN_CG1_CTRL, 0x4000); + mt6626_write(FM_MAIN_CG1_CTRL, 0); + + return ret; +} + +static fm_bool mt6626_SetFreq(fm_u16 freq) +{ + fm_u32 CHAN = 0x0000; + fm_u16 dataRead, cnt = 0, tempbuff = 0; + +Rampdown_again: + mt6626_RampDown(); + + fm_cb_op->cur_freq_set(freq); + CHAN = (freq - 640) << 1; + mt6626_read(FM_CHANNEL_SET, &dataRead); + + switch (Chip_Version) { + case mt6626_E1: + + if (((fm_u8)((dataRead & 0x1000) >> 12)) ^(channel_parameter[freq - 760] & 0x1)) { + mt6626_read(0x61, &tempbuff); + mt6626_write(0x60, 0x330F); + mt6626_write(0x61, 1); + mt6626_write(0x6e, 0x0); + mt6626_write(0x6e, 0x0); + mt6626_write(0x6e, 0x0); + mt6626_write(0x6e, 0x0); + mt6626_write(0x60, 0x0); + mt6626_write(0x60, 0x4000); + mt6626_write(0x60, 0x0); + mt6626_write(0x60, 0x3000); + mt6626_write(0x60, 0x3001); + Delayms(3); + mt6626_write(0x60, 0x3003); + mt6626_write(0x60, 0x3007); + mt6626_write(0x60, 0x300f); + mt6626_write(0x61, tempbuff | 0x3); + mt6626_write(0x61, tempbuff | 0x2); + mt6626_write(0x6A, 0x20); + mt6626_write(0x6B, 0x20); + Delayms(200); + } + + break; + case mt6626_E2: + break; + default: + break; + + } + + mt6626_writeFA(&dataRead, (channel_parameter[freq - 760])); + mt6626_write(FM_CHANNEL_SET, (dataRead&0xFC00) | CHAN); + + mt6626_TUNE_ON(); + + if (mt6626_WaitSTCDone(5000, 15)) { + if (cnt++ > 100) { + WCN_DBG(FM_ALT | CHIP, "set freq failed\n"); + return FALSE; + } else { + WCN_DBG(FM_WAR | CHIP, "set freq retry, cnt=%d\n", cnt); + goto Rampdown_again; + } + } + + mt6626_ClearSTCDone();//clear status flag + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + return TRUE; +} + +/* +* mt6626_Seek +* pFreq: IN/OUT parm, IN start freq/OUT seek valid freq +* return fm_true:seek success; fm_false:seek failed +*/ +static fm_bool mt6626_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space) +{ + fm_u16 dataRead; + fm_u16 freq_l; + fm_u16 freq_h; + + mt6626_RampDown(); + mt6626_Mute(fm_true); + + WCN_DBG(FM_DBG | CHIP, "min_freq:%d, max_freq:%d\n", min_freq, max_freq); + + //Program seek direction + mt6626_read(FM_MAIN_CFG1, &dataRead); + dataRead &= 0xFBFF; + + if (seekdir == 0) { + dataRead |= 0x0000; + } else { + dataRead |= 0x0400; + } + + WCN_DBG(FM_DBG | CHIP, "seek %s\n", seekdir ? "down" : "up"); + //Program scan channel spacing + dataRead &= 0x8FFF; + + if (space == 4) { + dataRead |= 0x4000; + } else { + dataRead |= 0x2000; + } + + WCN_DBG(FM_DBG | CHIP, "seek space %d\n", space); + //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap + dataRead &= 0xF7FF; + dataRead |= 0x0800; + //0x66[9:0] freq upper bound + max_freq = (max_freq - 640) * 2; + dataRead &= 0xFC00; + dataRead |= max_freq; + mt6626_write(FM_MAIN_CFG1, dataRead); + //0x67[9:0] freq lower bound + mt6626_read(FM_MAIN_CFG2, &dataRead); + min_freq = (min_freq - 640) * 2; + dataRead &= 0xFC00; + dataRead |= min_freq; + mt6626_write(FM_MAIN_CFG2, dataRead); + //Enable STC done intr + mt6626_set_bits(FM_MAIN_EXTINTRMASK, FM_EXT_STC_DONE_MASK, 0xFFFE); + mt6626_SEEK_ON(); + + if (fm_wait_stc_done(MT6626_FM_STC_DONE_TIMEOUT) == fm_false) { + WCN_DBG(FM_ALT | CHIP, "seek, get stc done failed\n"); + mt6626_set_bits(FM_MAIN_INTR, 0x0001, 0xFFFF); + mt6626_RampDown(); + return fm_false; + } + + //Disable STC done intr + mt6626_set_bits(FM_MAIN_EXTINTRMASK, 0, 0xFFFE); + //get the result freq + mt6626_read(FM_MAIN_CHANDETSTAT, &dataRead); + mt6626_write(FM_CHANNEL_SET, (dataRead&FM_HOST_CHAN) >> 4); + *pFreq = 640 + ((dataRead & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1)); + freq_l = fm_cust_config_fetch(FM_CFG_RX_BAND_FREQ_L); + freq_h = fm_cust_config_fetch(FM_CFG_RX_BAND_FREQ_H); + *pFreq = (*pFreq > freq_h) ? freq_h : *pFreq; + *pFreq = (*pFreq < freq_l) ? freq_l : *pFreq; + fm_cb_op->cur_freq_set(*pFreq); + WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq); + mt6626_Mute(fm_false); + + return fm_true; +} + +static fm_bool mt6626_Scan( + fm_u16 min_freq, fm_u16 max_freq, + fm_u16 *pFreq, + fm_u16 *pScanTBL, + fm_u16 *ScanTBLsize, + fm_u16 scandir, + fm_u16 space) +{ + fm_u16 tmp_reg, space_val, startfreq, offset = 0; + fm_u16 tmp_scanTBLsize = *ScanTBLsize; + fm_u16 dataRead; + + if ((!pScanTBL) || (tmp_scanTBLsize == 0)) { + WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n"); + return fm_false; + } + + WCN_DBG(FM_DBG | CHIP, "scan start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space); + + if (tmp_scanTBLsize > MT6626_SCANTBL_SIZE) { + tmp_scanTBLsize = MT6626_SCANTBL_SIZE; + } + + if (space == MT6626_FM_SPACE_200K) { + space_val = 2; //200K + } else if (space == MT6626_FM_SPACE_100K) { + space_val = 1; //100K + } else { + space_val = 1; //100K + } + + //scan up + if (scandir == MT6626_FM_SCAN_UP) { + startfreq = min_freq - space_val; + } else { + startfreq = max_freq + space_val;//max_freq compare need or not + } + + mt6626_RampDown(); + mt6626_Mute(fm_true); + + //set freq + if (fm_false == mt6626_SetFreq(startfreq)) { + WCN_DBG(FM_ALT | CHIP, "scan, failed set freq\n"); + return fm_false; + } + + mt6626_RampDown(); + + //set space(100k/200k)and band(min_freq~max_freq) and up/down and disable wrap + mt6626_read(FM_MAIN_CFG2, &dataRead); + mt6626_write(FM_MAIN_CFG2, (dataRead&0xFC00) | ((min_freq - 640) << 1));//set space(100k/200k)and band(875~1080)and up/down + mt6626_read(FM_MAIN_CFG1, &dataRead); + mt6626_write(FM_MAIN_CFG1, (dataRead&0x8800) | (scandir << 10) | (1 << (12 + space)) | ((max_freq - 640) << 1));//set space(100k/200k)and band(875~1080)and up/down + mt6626_read(FM_MAIN_CFG1, &dataRead); + mt6626_write(FM_MAIN_CFG1, dataRead&0xF7FF); //disable wrap , if it is auto scan function + + //Enable STC done intr + mt6626_set_bits(FM_MAIN_EXTINTRMASK, FM_EXT_STC_DONE_MASK, 0xFFFE); + //scan on + mt6626_SCAN_ON(); + + if (fm_wait_stc_done(MT6626_FM_STC_DONE_TIMEOUT) == fm_false) { + WCN_DBG(FM_ALT | CHIP, "scan, get stc done failed\n"); + mt6626_set_bits(FM_MAIN_INTR, 0x0001, 0xFFFF); + mt6626_RampDown(); + + //get the valid freq after scan + mt6626_read(FM_MAIN_CHANDETSTAT, &tmp_reg); + tmp_reg = 640 + ((tmp_reg & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1)); + *pFreq = tmp_reg; + WCN_DBG(FM_DBG | CHIP, "scan, failed freq:%d\n", *pFreq); + return fm_false; + } + + //Disable STC done intr + mt6626_set_bits(FM_MAIN_EXTINTRMASK, 0, 0xFFFE); + + //get scan Table + WCN_DBG(FM_DBG | CHIP, "mt6626_Scan tbl:"); + + for (offset = 0; offset < tmp_scanTBLsize; offset++) { + mt6626_read(FM_RDS_DATA_REG, &tmp_reg); + *(pScanTBL + offset) = tmp_reg; + } + + *ScanTBLsize = tmp_scanTBLsize; + + //get the valid freq after scan + mt6626_read(FM_MAIN_CHANDETSTAT, &tmp_reg); + tmp_reg = 640 + ((tmp_reg & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1)); + *pFreq = tmp_reg; + WCN_DBG(FM_DBG | CHIP, "scan, after scan freq:%d\n", *pFreq); + mt6626_Mute(fm_false); + + return fm_true; +} + +/* + * mt6626_GetCurRSSI - get current freq's RSSI value + * RS=RSSI + * If RS>511, then RSSI(dBm)= (RS-1024)/16*6 + * else RSSI(dBm)= RS/16*6 + */ +static fm_s32 mt6626_GetCurRSSI(fm_s32 *pRSSI) +{ + fm_u16 tmp_reg; + + mt6626_read(FM_RSSI_IND, &tmp_reg); + tmp_reg = tmp_reg & 0x03ff; + + if (pRSSI) { + *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4); + WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI); + } else { + WCN_DBG(FM_ERR | CHIP, "get rssi para error\n"); + return -FM_EPARA; + } + + return 0; +} + +static fm_s32 mt6626_SetVol(fm_u8 vol) +{ +#define MT6626_VOL_MAX 0x2B // 43 volume(0-15) + int ret = 0; + fm_u8 tmp_vol = vol & 0x3f; + fm_u16 tmp = 0; + + mt6626_read(0x60, &tmp); + mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0 + + tmp_vol = vol * 3; + if (tmp_vol > MT6626_VOL_MAX) + tmp_vol = MT6626_VOL_MAX; + + ret = mt6626_set_bits(0x9C, (tmp_vol << 8), 0xC0FF); + + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", tmp_vol); + return ret; + } else { + WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", tmp_vol); + } + + mt6626_write(0x60, tmp); //0x60 D3=1 + return 0; +} + +static fm_s32 mt6626_GetVol(fm_u8 *pVol) +{ + int ret = 0; + fm_u16 tmp_reg; + fm_u16 tmp = 0; + + FMR_ASSERT(pVol); + + mt6626_read(0x60, &tmp); + mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0 + + ret = mt6626_read(0x9C, &tmp_reg); + + if (ret) { + *pVol = 0; + WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n"); + return ret; + } else { + *pVol = (tmp_reg >> 8) & 0x3f; + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + } + + mt6626_write(0x60, tmp); //0x60 D3=1 + return 0; +} + +static fm_s32 mt6626_dump_reg(void) +{ + return 0; +} + +static fm_bool mt6626_GetMonoStereo(fm_u16 *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + fm_u16 TmpReg; + + if (pMonoStereo) { + mt6626_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return fm_false; + } + + WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo); + return fm_true; +} + +static fm_s32 mt6626_SetMonoStereo(fm_s32 MonoStereo) +{ + fm_s32 ret = 0; +#define FM_FORCE_MS 0x0008 + + WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + + mt6626_write(0x60, 0x3007); + + if (MonoStereo) { + ret = mt6626_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS); + } else { + ret = mt6626_set_bits(0x75, 0x0000, ~FM_FORCE_MS); + } + + return ret; +} + +static fm_s32 mt6626_GetCapArray(fm_s32 *ca) +{ + fm_u16 dataRead; + fm_u16 tmp = 0; + + FMR_ASSERT(ca); + mt6626_read(0x60, &tmp); + mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0 + + mt6626_read(0x25, &dataRead); + *ca = dataRead; + + mt6626_write(0x60, tmp); //0x60 D3=1 + return 0; +} + + +/* + * mt6626_GetCurPamd - get current freq's PAMD value + * PA=PAMD + * If PA>511 then PAMD(dB)= (PA-1024)/16*6, + * else PAMD(dB)=PA/16*6 + */ +static fm_bool mt6626_GetCurPamd(fm_u16 *pPamdLevl) +{ + fm_u16 tmp_reg; + fm_u16 dBvalue; + + if (mt6626_read(FM_ADDR_PAMD, &tmp_reg)) + return fm_false; + + tmp_reg &= 0x03FF; + dBvalue = (tmp_reg > 511) ? ((1024 - tmp_reg) * 6 / 16) : 0; + + *pPamdLevl = dBvalue; + return fm_true; +} + +static fm_s32 mt6626_ScanStop(void) +{ + return fm_force_active_event(FLAG_SCAN); +} + +static fm_s32 mt6626_SeekStop(void) +{ + return fm_force_active_event(FLAG_SEEK); +} + +/* + * mt6626_I2s_Setting - set the I2S state on MT6626 + * @onoff - I2S on/off + * @mode - I2S mode: Master or Slave + * + * Return:0, if success; error code, if failed + */ +static fm_s32 mt6626_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample) +{ + fm_u16 tmp_state = 0; + fm_u16 tmp_mode = 0; + fm_u16 tmp_sample = 0; + fm_s32 ret = 0; + + if (onoff == MT6626_I2S_ON) { + tmp_state = 0x0080; //I2S Frequency tracking on, 0x61 D7=1 + } else if (onoff == MT6626_I2S_OFF) { + tmp_state = 0x0000; //I2S Frequency tracking off, 0x61 D7=0 + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff); + ret = -FM_EPARA; + goto out; + } + + if (mode == MT6626_I2S_MASTER) { + tmp_mode = 0x03; //6620 as I2S master + } else if (mode == MT6626_I2S_SLAVE) { + tmp_mode = 0x0B; //6620 as I2S slave + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode); + ret = -FM_EPARA; + goto out; + } + + if (sample == MT6626_I2S_32K) { + tmp_sample = 0x0000; //6620 I2S 32KHz sample rate + } else if (sample == MT6626_I2S_44K) { + tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate + } else if (sample == MT6626_I2S_48K) { + tmp_sample = 0x1000; //6620 I2S 48KHz sample rate + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample); + ret = -FM_EPARA; + goto out; + } + + if ((ret = mt6626_set_bits(0x5F, tmp_sample, 0xE7FF))) + goto out; + + if ((ret = mt6626_write(0x9B, tmp_mode))) + goto out; + + if ((ret = mt6626_set_bits(0x61, tmp_state, 0xFF7F))) + goto out; + + WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n", + (onoff == MT6626_I2S_ON) ? "On" : "Off", + (mode == MT6626_I2S_MASTER) ? "Master" : "Slave", + sample); +out: + return ret; +} + +static fm_bool mt6626_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value) +{ + return fm_true; +} + +static fm_s32 fm_low_power_wa_default(fm_s32 fmon) +{ + return 0; +} + +fm_s32 fm_low_ops_register(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + //Basic functions. + + FMR_ASSERT(ops); + FMR_ASSERT(ops->cb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb_op = &ops->cb; + + //ops->bi.low_pwr_wa = mt6626_low_pwr_wa; + ops->bi.low_pwr_wa = fm_low_power_wa_default; + ops->bi.pwron = mt6626_pwron; + ops->bi.pwroff = mt6626_pwroff; + ops->bi.msdelay = Delayms; + ops->bi.usdelay = Delayus; + ops->bi.read = mt6626_read; + ops->bi.write = mt6626_write; + ops->bi.setbits = mt6626_set_bits; + ops->bi.chipid_get = mt6626_get_chipid; + ops->bi.mute = mt6626_Mute; + ops->bi.rampdown = mt6626_RampDown; + ops->bi.pwrupseq = mt6626_PowerUp; + ops->bi.pwrdownseq = mt6626_PowerDown; + ops->bi.setfreq = mt6626_SetFreq; + ops->bi.seek = mt6626_Seek; + ops->bi.seekstop = mt6626_SeekStop; + ops->bi.scan = mt6626_Scan; + ops->bi.scanstop = mt6626_ScanStop; + ops->bi.rssiget = mt6626_GetCurRSSI; + ops->bi.volset = mt6626_SetVol; + ops->bi.volget = mt6626_GetVol; + ops->bi.dumpreg = mt6626_dump_reg; + ops->bi.msget = mt6626_GetMonoStereo; + ops->bi.msset = mt6626_SetMonoStereo; + ops->bi.pamdget = mt6626_GetCurPamd; + ops->bi.em = mt6626_em_test; + ops->bi.anaswitch = mt6626_SetAntennaType; + ops->bi.anaget = mt6626_GetAntennaType; + ops->bi.caparray_get = mt6626_GetCapArray; + ops->bi.i2s_set = mt6626_I2s_Setting; + + return ret; +} + +fm_s32 fm_low_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + //Basic functions. + + FMR_ASSERT(ops); + + fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface)); + return ret; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c new file mode 100755 index 000000000000..600245d68d71 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c @@ -0,0 +1,242 @@ +/* mt6626_fm_link.c + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6626 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +#include "mt6626_fm.h" +#include "mt6626_fm_link.h" +#include "mt6626_fm_reg.h" + +//these functions are defined after Linux2.6.32 +static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +static int fm_i2c_remove(struct i2c_client *client); + + +static const struct i2c_device_id fm_i2c_id = {MT6626_DEV, 0}; +static unsigned short force[] = {MT6626_I2C_PORT, MT6626_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END}; +static const unsigned short * const forces[] = {force, NULL}; +static struct i2c_client_address_data addr_data = { + .forces = forces +}; + +struct i2c_driver MT6626_driver = { + .probe = fm_i2c_probe, + .remove = fm_i2c_remove, + .detect = fm_i2c_detect, + .driver.name = MT6626_DEV, + .id_table = &fm_i2c_id, + .address_data = &addr_data, +}; + +static struct i2c_client *g_client; + +static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + + WCN_DBG(FM_NTC | LINK, "%s\n", __func__); + g_client = client; + + return ret; +} + +static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + WCN_DBG(FM_NTC | LINK, "%s\n", __func__); + strcpy(info->type, MT6626_DEV); + return 0; +} + +static int fm_i2c_remove(struct i2c_client *client) +{ + WCN_DBG(FM_NTC | LINK, "%s\n", __func__); + return 0; +} + +static struct fm_link_event *link_event; + +fm_s32 fm_link_setup(void* data) +{ + if (!(link_event = kzalloc(sizeof(struct fm_link_event), GFP_KERNEL))) { + WCN_DBG(FM_ALT | LINK, "kzalloc(fm_link_event) -ENOMEM\n"); + return -1; +} + + link_event->ln_event = fm_flag_event_create("ln_evt"); + + if (!link_event->ln_event) { + WCN_DBG(FM_ALT | LINK, "create mt6626_ln_event failed\n"); + fm_free(link_event); + return -1; + } + + fm_flag_event_get(link_event->ln_event); + + WCN_DBG(FM_NTC | LINK, "fm link setup\n"); + return i2c_add_driver(&MT6626_driver); +} + +fm_s32 fm_link_release(void) +{ + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + WCN_DBG(FM_NTC | LINK, "fm link release\n"); + i2c_del_driver(&MT6626_driver); + return 0; +} + +/* + * fm_ctrl_rx + * the low level func to read a rigister + * @addr - rigister address + * @val - the pointer of target buf + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val) +{ + fm_s32 n; + fm_u8 b[2] = {0}; + + // first, send addr to MT6626 + n = i2c_master_send(g_client, (fm_u8*) & addr, 1); + + if (n < 0) { + WCN_DBG(FM_ALT | LINK, "rx 1, [addr=0x%02X] [err=%d]\n", addr, n); + return -1; + } + + // second, receive two byte from MT6626 + n = i2c_master_recv(g_client, b, 2); + + if (n < 0) { + WCN_DBG(FM_ALT | LINK, "rx 2, [addr=0x%02X] [err=%d]\n", addr, n); + return -2; + } + + *val = ((fm_u16)b[0] << 8 | (fm_u16)b[1]); + + return 0; +} + +/* + * fm_ctrl_tx + * the low level func to write a rigister + * @addr - rigister address + * @val - value will be writed in the rigister + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val) +{ + fm_s32 n; + fm_u8 b[3]; + + b[0] = addr; + b[1] = (fm_u8)(val >> 8); + b[2] = (fm_u8)(val & 0xFF); + + n = i2c_master_send(g_client, b, 3); + + if (n < 0) { + WCN_DBG(FM_ALT | LINK, "tx, [addr=0x%02X] [err=%d]\n", addr, n); + return -1; + } + + return 0; +} + +/* + * fm_cmd_tx() - send cmd to FM firmware and wait event + * @buf - send buffer + * @len - the length of cmd + * @mask - the event flag mask + * @ cnt - the retry conter + * @timeout - timeout per cmd + * Return 0, if success; error code, if failed + */ +fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result)) +{ + return 0; +} + +fm_bool fm_wait_stc_done(fm_u32 sec) +{ + fm_s32 ret_time = 0; + + ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, FLAG_TEST, sec); + if (!ret_time) { + WCN_DBG(FM_WAR | LINK, "wait stc done fail\n"); + return fm_false; + } else { + WCN_DBG(FM_DBG | LINK, "wait stc done ok\n"); + } + + FM_EVENT_CLR(link_event->ln_event, FLAG_TEST); + return fm_true; +} + +fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32)) +{ + fm_u16 tmp_reg; + + fm_ctrl_rx(FM_MAIN_INTR, &tmp_reg); + + if (tmp_reg&FM_INTR_STC_DONE) { + //clear status flag + fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_STC_DONE); + FM_EVENT_SEND(link_event->ln_event, FLAG_TEST); + } + + if (tmp_reg&FM_INTR_RDS) { + //clear status flag + fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_RDS); + + /*Handle the RDS data that we get*/ + if (rds_parser) { + rds_parser(NULL, 0); //mt6626 rds lib will get rds raw data by itself + } else { + WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n"); + } + } + + return 0; +} + +fm_s32 fm_force_active_event(fm_u32 mask) +{ + FM_EVENT_SEND(link_event->ln_event, FLAG_TEST); + return 0; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c new file mode 100755 index 000000000000..3f4ccd0baa53 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c @@ -0,0 +1,320 @@ +/* mt6626_rds.c + * + * (C) Copyright 2009 + * MediaTek + * hongcheng + * + * mt6626 FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" + +#include "mt6626_fm_reg.h" + + +static fm_bool bRDS_FirstIn = fm_false; +static fm_u32 gBLER_CHK_INTERVAL = 5000; +static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0; +static fm_u8 BAD_BLK_RATIO = 0; + +static struct fm_callback *fm_cb = NULL; +static struct fm_basic_interface *fm_bi = NULL; + + +static fm_bool mt6626_RDS_support(void); +static fm_s32 mt6626_RDS_enable(void); +static fm_s32 mt6626_RDS_disable(void); +static fm_u16 mt6626_RDS_Get_GoodBlock_Counter(void); +static fm_u16 mt6626_RDS_Get_BadBlock_Counter(void); +static fm_u8 mt6626_RDS_Get_BadBlock_Ratio(void); +static fm_u32 mt6626_RDS_Get_BlerCheck_Interval(void); +static void mt6626_RDS_GetData(fm_u16 *data, fm_u16 datalen); +static void mt6626_RDS_Init_Data(rds_t *pstRDSData); + + + +static fm_bool mt6626_RDS_support(void) +{ + return fm_true; +} + +static fm_s32 mt6626_RDS_enable(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + fm_bi->read(FM_RDS_CFG0, &dataRead); + fm_bi->write(FM_RDS_CFG0, 6); //set buf_start_th + fm_bi->read(FM_MAIN_CTRL, &dataRead); + fm_bi->write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + + return 0; +} + +static fm_s32 mt6626_RDS_disable(void) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + fm_bi->read(FM_MAIN_CTRL, &dataRead); + fm_bi->write(FM_MAIN_CTRL, dataRead&(~RDS_MASK)); + + return 0; +} + +static fm_u16 mt6626_RDS_Get_GoodBlock_Counter(void) +{ + fm_u16 tmp_reg; + + fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u16 mt6626_RDS_Get_BadBlock_Counter(void) +{ + fm_u16 tmp_reg; + + fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u8 mt6626_RDS_Get_BadBlock_Ratio(void) +{ + fm_u16 tmp_reg; + fm_u16 gbc; + fm_u16 bbc; + + gbc = mt6626_RDS_Get_GoodBlock_Counter(); + bbc = mt6626_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) { + tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc)); + } else { + tmp_reg = 0; + } + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_s32 mt6626_RDS_BlockCounter_Reset(void) +{ + mt6626_RDS_disable(); + mt6626_RDS_enable(); + + return 0; +} + +static fm_u32 mt6626_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static fm_s32 mt6626_RDS_BlerCheck(rds_t *dst) +{ + return -1; +} + +static void RDS_Recovery_Handler(void) +{ + fm_u16 tempData = 0; + + do { + fm_bi->read(FM_RDS_DATA_REG, &tempData); + fm_bi->read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} + +static void mt6626_RDS_GetData(fm_u16 *data, fm_u16 datalen) +{ +#define RDS_GROUP_DIFF_OFS 0x007C +#define RDS_FIFO_DIFF 0x007F +#define RDS_CRC_BLK_ADJ 0x0020 +#define RDS_CRC_CORR_CNT 0x001E +#define RDS_CRC_INFO 0x0001 + + fm_u16 CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + fm_u16 temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_bi->read(FM_RDS_FIFO_STATUS0, &temp); + RDSDataCount = ((RDS_GROUP_DIFF_OFS & temp) << 2); + + if ((temp & RDS_FIFO_DIFF) >= 4) { + //block A data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 10; + CRC |= (temp & RDS_CRC_INFO) << 3; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 11); + fm_bi->read(FM_RDS_DATA_REG, &data[0]); + + //block B data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 9; + CRC |= (temp & RDS_CRC_INFO) << 2; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 7); + fm_bi->read(FM_RDS_DATA_REG, &data[1]); + + //block C data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 8; + CRC |= (temp & RDS_CRC_INFO) << 1; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 3); + fm_bi->read(FM_RDS_DATA_REG, &data[2]); + + //block D data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 7; + CRC |= (temp & RDS_CRC_INFO); + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) >> 1); + fm_bi->read(FM_RDS_DATA_REG, &data[3]); + + data[4] = FM_WARorrCnt; // CBC + data[5] = (CRC | RDS_adj | RDSDataCount); //CRC + + fm_bi->read(FM_RDS_PWDI, &data[6]); + fm_bi->read(FM_RDS_PWDQ, &data[7]); + + fm_bi->read(FM_RDS_POINTER, &OutputPofm_s32); + + //Go fm_s32o RDS recovery handler while RDS output pofm_s32 doesn't align to 4 in numeric + if (OutputPofm_s32 & 0x3) { + RDS_Recovery_Handler(); + } + + } else { + for (; i < 8; i++) + data[i] = 0; + } +} + +static void mt6626_RDS_Init_Data(rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(rds_t)); + bRDS_FirstIn = fm_true; + + fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData)); + fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS)); + fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON)); +} + +fm_bool mt6626_RDS_OnOff(rds_t *dst, fm_bool bFlag) +{ + if (mt6626_RDS_support() == fm_false) { + WCN_DBG(FM_ALT | RDSC, "mt6626_RDS_OnOff failed, RDS not support\n"); + return fm_false; + } + + if (bFlag) { + mt6626_RDS_Init_Data(dst); + mt6626_RDS_enable(); + } else { + mt6626_RDS_disable(); + } + + return fm_true; +} + +DEFINE_RDSLOG(rds_log); + +/* mt6626_RDS_Efm_s32_Handler - response FM RDS interrupt + * @fm - main data structure of FM driver + * This function first get RDS raw data, then call RDS spec parser + */ +static fm_s32 mt6626_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)) +{ + struct rds_rx_t raw; + fm_u16 fifo_offset; + + do { + mt6626_RDS_GetData(&raw.data[0].blkA, sizeof(rds_packet_t) + 2); + fifo_offset = (raw.data[0].crc & FM_RDS_DCO_FIFO_OFST) >> 5; //FM_RDS_DATA_CRC_FFOST + WCN_DBG(FM_DBG | RDSC, "RDS fifo_offset:%d\n", fifo_offset); + rds_log.log_in(&rds_log, &raw, sizeof(rds_packet_t) + 2*sizeof(fm_u16)); + rds_parser(rds_dst, &raw, sizeof(rds_packet_t) + 2*sizeof(fm_u16), getfreq); + } while (fifo_offset > 1); + + return 0; +} + +static fm_s32 mt6626_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len) +{ + return rds_log.log_out(&rds_log, dst, dst_len); +} + +static fm_s32 mt6626_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static fm_s32 mt6626_rds_gc_reset(rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +fm_s32 fm_rds_ops_register(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + FMR_ASSERT(ops->bi.write); + FMR_ASSERT(ops->bi.read); + FMR_ASSERT(ops->bi.setbits); + FMR_ASSERT(ops->bi.usdelay); + fm_bi = &ops->bi; + + FMR_ASSERT(ops->cb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb = &ops->cb; + + ops->ri.rds_blercheck = mt6626_RDS_BlerCheck; + ops->ri.rds_onoff = mt6626_RDS_OnOff; + ops->ri.rds_parser = mt6626_rds_parser; + ops->ri.rds_gbc_get = mt6626_RDS_Get_GoodBlock_Counter; + ops->ri.rds_bbc_get = mt6626_RDS_Get_BadBlock_Counter; + ops->ri.rds_bbr_get = mt6626_RDS_Get_BadBlock_Ratio; + ops->ri.rds_bc_reset = mt6626_RDS_BlockCounter_Reset; + ops->ri.rds_bci_get = mt6626_RDS_Get_BlerCheck_Interval; + ops->ri.rds_log_get = mt6626_rds_log_get; + ops->ri.rds_gc_get = mt6626_rds_gc_get; + ops->ri.rds_gc_reset = mt6626_rds_gc_reset; + return ret; +} + +fm_s32 fm_rds_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + + fm_bi = NULL; + fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h new file mode 100755 index 000000000000..f333f7edda4b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h @@ -0,0 +1,10639 @@ + +const unsigned char channel_parameter[] = { +0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,5 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,2 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,0 +,1 +,1 +,1 +,0 +,0 +,0 +}; + +#if defined(MT6626_FPGA) +const unsigned short bin_rom[] = { +0x0000 +,0x1FFF +,0xBC00 +,0x0010 +,0xBC00 +,0x0271 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0x8EC8 +,0x8E00 +,0xBC02 +,0x0906 +,0xBC20 +,0x2019 +,0x4021 +,0xFB11 +,0xBC02 +,0x0807 +,0xBC20 +,0x2019 +,0x4041 +,0xFB11 +,0xBC22 +,0x0480 +,0xBC20 +,0x0080 +,0x4001 +,0x8B02 +,0xE401 +,0xBC21 +,0x0367 +,0xA301 +,0x0080 +,0xBC20 +,0x201A +,0x41E1 +,0xFA12 +,0xA302 +,0x0082 +,0x0891 +,0x2620 +,0x8FF9 +,0x3D02 +,0xBC21 +,0x2018 +,0x481E +,0xBC22 +,0x2019 +,0x8C69 +,0x40C0 +,0xA203 +,0x0082 +,0x2631 +,0x8F4B +,0x2634 +,0x8F3E +,0x2632 +,0x8F1D +,0xB306 +,0x0008 +,0x8F0A +,0x40E0 +,0xFB50 +,0xBC02 +,0x1E58 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8C53 +,0x40C0 +,0xFB50 +,0xFA33 +,0x26B0 +,0x8F08 +,0xBC02 +,0x072A +,0xBC21 +,0x2018 +,0x4020 +,0x7207 +,0xBB30 +,0x40C0 +,0xBC22 +,0x2019 +,0xA31E +,0x0082 +,0x8D41 +,0x40A0 +,0x70E0 +,0x3B50 +,0xBC21 +,0x201D +,0xBC22 +,0x201B +,0xFA31 +,0xFA52 +,0x0810 +,0xBC3E +,0x00E4 +,0xBC3A +,0x0692 +,0xB400 +,0x0002 +,0xA31E +,0x0083 +,0xA31A +,0x0084 +,0x0408 +,0xBC02 +,0x0131 +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8D23 +,0x4080 +,0xFB50 +,0xBC02 +,0x016B +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0x8D18 +,0x4060 +,0xBC21 +,0x201F +,0xFB50 +,0xFA30 +,0xBC3E +,0x00C8 +,0xBC3A +,0x0652 +,0xBC21 +,0x03FF +,0xA31E +,0x0083 +,0xA31A +,0x0084 +,0x0801 +,0xBC02 +,0x0131 +,0x40C0 +,0xBC22 +,0x2019 +,0xBC21 +,0x2018 +,0x481E +,0xA203 +,0x0082 +,0xB316 +,0x0040 +,0x8F91 +,0xBC00 +,0x001C +,0x6915 +,0xA902 +,0x8E00 +,0xA30E +,0x0085 +,0xDFD5 +,0xBC02 +,0x0607 +,0xBC02 +,0x077A +,0xBC20 +,0x2019 +,0x7040 +,0x4FD5 +,0xBC22 +,0x2008 +,0xFB11 +,0xFA51 +,0xBC23 +,0x4000 +,0x0ACB +,0xBC21 +,0x2100 +,0xFB53 +,0xFA32 +,0xB314 +,0x0020 +,0x8FFB +,0x4121 +,0xE9FE +,0xFB11 +,0xBC00 +,0x1D52 +,0xE902 +,0xBC20 +,0x2019 +,0x7060 +,0x5FD5 +,0x8C02 +,0xFB11 +,0x8E00 +,0xA200 +,0x008B +,0x2600 +,0x8FFA +,0x3E02 +,0xA200 +,0x008C +,0x6980 +,0x4FD5 +,0x8F02 +,0xA200 +,0x0086 +,0x2681 +,0x8F02 +,0x4080 +,0xA300 +,0x0082 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0xBC20 +,0x2019 +,0x7068 +,0x5FD5 +,0x8C02 +,0xFB11 +,0x8E00 +,0xA200 +,0x008B +,0x2600 +,0x8FFA +,0x3E02 +,0xA200 +,0x008C +,0xA201 +,0x0088 +,0x2681 +,0x8F06 +,0x4020 +,0xA202 +,0x008A +,0x1401 +,0x0A10 +,0xA300 +,0x008A +,0x3409 +,0xA300 +,0x0088 +,0xA201 +,0x0086 +,0xB300 +,0x0010 +,0x8F01 +,0x2691 +,0x8F09 +,0x401C +,0xBC20 +,0x2041 +,0xA202 +,0x008A +,0xA31C +,0x0088 +,0xA31C +,0x008A +,0xFB12 +,0x2691 +,0x8F16 +,0xBC20 +,0x2019 +,0x41C1 +,0x7008 +,0x7B11 +,0xBC22 +,0x2018 +,0xBC20 +,0x201A +,0x8C05 +,0xFB51 +,0x8E00 +,0xBC20 +,0x201A +,0x8E00 +,0xFA10 +,0xB310 +,0x0008 +,0x8FF6 +,0x7040 +,0x0FD5 +,0x8C03 +,0xA300 +,0x0082 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x05A2 +,0xA200 +,0x0087 +,0x2680 +,0x8F0C +,0xBC20 +,0x2040 +,0x7000 +,0x4FC3 +,0x700F +,0xBB11 +,0x4042 +,0xA303 +,0x0089 +,0xA31E +,0x0087 +,0xA301 +,0x0086 +,0xFB12 +,0xA200 +,0x0084 +,0x8EA0 +,0xBC20 +,0x02C7 +,0xA300 +,0x009B +,0xBC02 +,0x00A7 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x033D +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7000 +,0x4FF5 +,0xBC22 +,0x201A +,0x7040 +,0x3B11 +,0xFA51 +,0x2248 +,0x8F00 +,0xA300 +,0x0082 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0480 +,0xBC20 +,0x02B3 +,0xA300 +,0x009B +,0xBC02 +,0x00A7 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x03F7 +,0xBC22 +,0x2018 +,0x7008 +,0x3B11 +,0x7050 +,0x3B50 +,0xBC21 +,0x2019 +,0x8C2E +,0xFB30 +,0xA200 +,0x0081 +,0x2601 +,0x8F04 +,0xBC21 +,0x8000 +,0xBC20 +,0x2023 +,0x8C24 +,0xFB11 +,0xBC02 +,0x01BE +,0xA200 +,0x0085 +,0x4001 +,0xA301 +,0x0081 +,0x2682 +,0x8F02 +,0x4100 +,0xA300 +,0x0082 +,0xBC02 +,0x1E58 +,0xBC20 +,0x201A +,0x8E00 +,0xFA10 +,0xB310 +,0x0008 +,0x8F05 +,0xBC20 +,0x2019 +,0x4161 +,0x7008 +,0x3B11 +,0xA300 +,0x0085 +,0xBC02 +,0x077A +,0xBC20 +,0x2023 +,0xBC21 +,0x8000 +,0xFB11 +,0xA200 +,0x0082 +,0x2604 +,0x8FCE +,0x3E02 +,0x7000 +,0x4FD5 +,0xBC20 +,0x2008 +,0x8EC0 +,0xE9FE +,0xFB11 +,0xE902 +,0xA200 +,0x0098 +,0x6CE0 +,0x1FD5 +,0x8F57 +,0xBC02 +,0x0918 +,0xBC20 +,0x01AE +,0xBC02 +,0x09F0 +,0xA200 +,0x02A7 +,0x2682 +,0x8F02 +,0xBC20 +,0x01AE +,0xBC02 +,0x0D50 +,0xA200 +,0x008E +,0x2606 +,0x8F1E +,0x2604 +,0x8F17 +,0x2602 +,0x8F0B +,0x2600 +,0x8F05 +,0xA200 +,0x008D +,0x2680 +,0x8F20 +,0xBC02 +,0x0BDE +,0x8D1F +,0xBC02 +,0x0E6E +,0x8D1C +,0xBC20 +,0x2032 +,0x4101 +,0xFA10 +,0x0801 +,0xA300 +,0x01E3 +,0xBC02 +,0x0A17 +,0x8D12 +,0xBC02 +,0x0AA2 +,0xBC02 +,0x0CA4 +,0x8D0D +,0xA200 +,0x0085 +,0x2601 +,0x8F05 +,0xA200 +,0x02C7 +,0x2601 +,0x8F01 +,0xBC02 +,0x0B48 +,0x8D02 +,0xBC02 +,0x0B2B +,0xA201 +,0x01BE +,0xBC20 +,0x01AE +,0xBC02 +,0x0A72 +,0xBC20 +,0x01E7 +,0xBC02 +,0x0B04 +,0xA200 +,0x0266 +,0x2680 +,0xBC20 +,0x01E7 +,0x8F03 +,0xBC21 +,0x7FFF +,0xBC02 +,0x0B8C +,0x8D04 +,0xA201 +,0x01FF +,0xBC02 +,0x0B8C +,0xBC02 +,0x0C54 +,0xA200 +,0x0099 +,0x2600 +,0x8F02 +,0xBC02 +,0x195E +,0xBC02 +,0x1926 +,0xA200 +,0x009A +,0x2600 +,0x8F02 +,0xB000 +,0xFFFF +,0xA300 +,0x009A +,0xBC20 +,0x2040 +,0x4021 +,0xFA10 +,0x0801 +,0x2600 +,0x8F0A +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0xFA10 +,0x0801 +,0x2680 +,0x8F02 +,0xA200 +,0x009A +,0x2600 +,0x8F15 +,0x3E02 +,0x4000 +,0xA300 +,0x0099 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0x0080 +,0xFA12 +,0x0851 +,0x2610 +,0x8F0B +,0xFA11 +,0xBC22 +,0xFF7F +,0x084A +,0x7000 +,0x3B11 +,0xBC02 +,0x05B3 +,0x8D03 +,0x4020 +,0xA300 +,0x0099 +,0x7038 +,0x4FD5 +,0xA200 +,0x008E +,0xE9FE +,0x3401 +,0x8EC0 +,0x0801 +,0xA300 +,0x008E +,0x4020 +,0xBC21 +,0x00C0 +,0xA300 +,0x0091 +,0xA300 +,0x0092 +,0xA301 +,0x0098 +,0x8EC0 +,0xA300 +,0x0090 +,0xA300 +,0x008F +,0xE918 +,0x8E00 +,0xDD05 +,0xBC25 +,0x2096 +,0xDD5B +,0xFAB5 +,0xA205 +,0x009B +,0xDD7A +,0xDD9F +,0xDDBE +,0xDDDD +,0xDDFC +,0xDE0B +,0xDE2C +,0xDE49 +,0xDE68 +,0xDE8F +,0xDEAE +,0xDED5 +,0xDEE6 +,0xDF04 +,0xDF23 +,0xDF42 +,0xDF61 +,0xDF80 +,0xDD27 +,0xF9FC +,0x8EA5 +,0xBC20 +,0x2096 +,0xBC21 +,0x00FF +,0xFA10 +,0x6220 +,0x4D05 +,0xA203 +,0x0096 +,0x6854 +,0xCD27 +,0x6624 +,0xCF80 +,0xA302 +,0x0096 +,0xCF61 +,0xCF42 +,0xCF23 +,0xCF04 +,0xCEE6 +,0xCDFC +,0xCDDD +,0xCDBE +,0xCD9F +,0xCD7A +,0xCD5B +,0xF8FC +,0xCED5 +,0xCEAE +,0xCE8F +,0xCE68 +,0xCE49 +,0xCE2C +,0xCE0B +,0xE9E8 +,0x8EC8 +,0xBC20 +,0x2102 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x6980 +,0x2902 +,0x8F07 +,0xDFD5 +,0xBC02 +,0x02DB +,0xBC20 +,0x02DB +,0xCFD5 +,0xA300 +,0x009B +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x2104 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x6980 +,0x2902 +,0x8F07 +,0xDFD5 +,0xBC02 +,0x0423 +,0xBC20 +,0x0423 +,0xCFD5 +,0xA300 +,0x009B +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE906 +,0xA202 +,0x0090 +,0x69A8 +,0x1F95 +,0x8F19 +,0xBC24 +,0x2081 +,0xBC23 +,0x2082 +,0xFA95 +,0xBC24 +,0x2015 +,0xFA73 +,0xA21A +,0x0461 +,0xA21E +,0x046B +,0xA210 +,0x0361 +,0xFA94 +,0xA305 +,0x02CA +,0xA303 +,0x02CB +,0xA310 +,0x02C8 +,0xA31A +,0x02C9 +,0xA304 +,0x02CC +,0xA31E +,0x02CD +,0x26A6 +,0x8F32 +,0xBC23 +,0x027F +,0xBC24 +,0x026F +,0x4022 +,0xBD10 +,0x0306 +,0xE205 +,0xE585 +,0xA21C +,0x02C8 +,0xA21A +,0x02CA +,0xA21E +,0x02CB +,0xA210 +,0x02C9 +,0xA205 +,0x02CC +,0xA203 +,0x02CD +,0xA204 +,0x0081 +,0xA31C +,0x02C2 +,0xA310 +,0x02C3 +,0xA31A +,0x02C4 +,0xA31E +,0x02C5 +,0xA305 +,0x02C6 +,0xA303 +,0x02C7 +,0x2640 +,0x8F03 +,0xA203 +,0x0095 +,0x34D9 +,0xA303 +,0x0095 +,0xA203 +,0x0098 +,0xA302 +,0x0081 +,0x3230 +,0x8F02 +,0xB026 +,0xFFFF +,0xA302 +,0x0098 +,0xA200 +,0x028F +,0x421E +,0x403A +,0xBC3C +,0x027F +,0xBC22 +,0x2033 +,0xE064 +,0xBC23 +,0x2034 +,0xE065 +,0xFB54 +,0xFB75 +,0xA300 +,0x028F +,0xBC02 +,0x1BC3 +,0xBC22 +,0x3105 +,0xA200 +,0x0313 +,0x700E +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2139 +,0xBC3C +,0x02E0 +,0xBD05 +,0x0352 +,0xFA53 +,0xE463 +,0xA202 +,0x0099 +,0x2620 +,0xA300 +,0x0313 +,0x385A +,0x8F10 +,0xBC23 +,0x2008 +,0xBC24 +,0x0080 +,0xFA75 +,0x0B2C +,0xBC25 +,0x2103 +,0xFB74 +,0xFAB3 +,0xBC24 +,0x4000 +,0x08DC +,0x2630 +,0x8F01 +,0xBC02 +,0x15BE +,0x4022 +,0xA203 +,0x0091 +,0x26B0 +,0x8F05 +,0xBC20 +,0x2012 +,0xBC21 +,0x2014 +,0xBC02 +,0x106C +,0x4022 +,0xA203 +,0x0093 +,0xB306 +,0x0011 +,0x4003 +,0x1893 +,0xA204 +,0x0091 +,0x6D28 +,0x5FA2 +,0x4244 +,0x2214 +,0x18DA +,0xA202 +,0x008F +,0x2620 +,0xA303 +,0x0091 +,0x8F67 +,0x2621 +,0x8F53 +,0x2622 +,0x8F2B +,0x26A3 +,0x8F26 +,0xBC02 +,0x118C +,0xCFA2 +,0x2620 +,0xBC20 +,0x2015 +,0x8F0E +,0xA201 +,0x0097 +,0xBC02 +,0x101D +,0xBC02 +,0x1391 +,0xBC02 +,0x1DAA +,0xA202 +,0x0097 +,0x2622 +,0x4043 +,0x8F00 +,0x34D1 +,0xA303 +,0x0097 +,0xA202 +,0x0093 +,0x3511 +,0x4242 +,0x21E2 +,0xA203 +,0x0094 +,0x4005 +,0x34D9 +,0x192C +,0x4062 +,0x08DA +,0xA304 +,0x0093 +,0x8C51 +,0xA303 +,0x0094 +,0x8C4E +,0x4062 +,0x3854 +,0xB004 +,0xFFFB +,0xDFC0 +,0xBC02 +,0x121B +,0x6E15 +,0x0FC0 +,0xB014 +,0xFFFA +,0xDFC1 +,0xBC02 +,0x1277 +,0xBC02 +,0x12BC +,0xCFC0 +,0xBC21 +,0x0464 +,0xBC02 +,0x1326 +,0x7018 +,0x8FA3 +,0x2630 +,0x8F33 +,0xA201 +,0x0097 +,0xBC20 +,0x2013 +,0xBC02 +,0x1037 +,0xA201 +,0x0097 +,0xBC20 +,0x200B +,0xBC02 +,0x1092 +,0x4062 +,0x8D27 +,0xBC02 +,0x118C +,0xBC02 +,0x11E4 +,0xBC02 +,0x1B03 +,0x7018 +,0x8FA3 +,0x2630 +,0x8F1B +,0xA201 +,0x0097 +,0xBC20 +,0x2011 +,0xBC02 +,0x10B6 +,0x4062 +,0x8D15 +,0xBC02 +,0x12BC +,0xCFA2 +,0x2620 +,0x8F00 +,0xBC02 +,0x1E00 +,0xBC02 +,0x10FF +,0xA202 +,0x0094 +,0x26A0 +,0x4062 +,0x8F05 +,0xA203 +,0x047B +,0x2630 +,0x8F01 +,0xBC02 +,0x115E +,0x4062 +,0xA204 +,0x008F +,0xA203 +,0x0090 +,0x6D48 +,0x4F95 +,0x34D9 +,0x40E6 +,0xA205 +,0x008D +,0x08DE +,0x08A2 +,0x26D0 +,0xA303 +,0x0090 +,0xA302 +,0x008F +,0x8F04 +,0xBC22 +,0x31F8 +,0xDF95 +,0xFA52 +,0x8EA2 +,0xCF95 +,0x8E00 +,0x8EC0 +,0xE9FA +,0x8E00 +,0xE902 +,0xA200 +,0x0092 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x10DC +,0xCFC0 +,0xB300 +,0x0044 +,0x8F2B +,0xA201 +,0x0097 +,0xB300 +,0x0045 +,0x8F21 +,0xB300 +,0x0046 +,0x8F14 +,0xCFC0 +,0xB310 +,0x0047 +,0x8F21 +,0xA200 +,0x0470 +,0x2680 +,0x8F00 +,0xBC02 +,0x0F91 +,0xBC02 +,0x1DAA +,0xA200 +,0x0097 +,0x2602 +,0x4041 +,0x8F00 +,0x3441 +,0xA301 +,0x0097 +,0x8D12 +,0xBC20 +,0x2013 +,0xBC02 +,0x1037 +,0xA201 +,0x0097 +,0xBC20 +,0x200B +,0xBC02 +,0x1092 +,0x8D07 +,0xBC20 +,0x2011 +,0xBC02 +,0x10B6 +,0x8D02 +,0xBC02 +,0x1E00 +,0x7240 +,0x4FC0 +,0x6D00 +,0x4FF5 +,0x21C1 +,0x4001 +,0x1808 +,0xA201 +,0x008D +,0x2690 +,0xA300 +,0x0092 +,0x8F04 +,0xBC20 +,0x31F8 +,0xDFD5 +,0xFA10 +,0x8EA0 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x009C +,0xBC21 +,0x047C +,0x0448 +,0x3489 +,0x32A0 +,0x4001 +,0x8F01 +,0x8B02 +,0xE401 +,0x8EB8 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0474 +,0xBC20 +,0x3173 +,0xBC21 +,0x3010 +,0xBC24 +,0x02A8 +,0xBC22 +,0x2032 +,0x7014 +,0x3A10 +,0x4085 +,0x700F +,0x3A31 +,0xA300 +,0x01E5 +,0xFA53 +,0xBC40 +,0x1605 +,0xA301 +,0x0467 +,0x4100 +,0xBC40 +,0x1E10 +,0xBC40 +,0x2610 +,0x6206 +,0x2610 +,0xFA51 +,0x6213 +,0x6650 +,0xBC3A +,0x0184 +,0xBC3E +,0x01C0 +,0x4503 +,0x4444 +,0xBC2E +,0x0160 +,0xBC2F +,0x0170 +,0xB048 +,0x009C +,0xB056 +,0x009C +,0xA300 +,0x01E3 +,0xA301 +,0x01F7 +,0xA31C +,0x0468 +,0xA31C +,0x0461 +,0xA31C +,0x045C +,0xA30E +,0x016E +,0xA30F +,0x017E +,0xA31A +,0x01AC +,0xA31A +,0x01AD +,0xA31E +,0x01E0 +,0xA31E +,0x01E1 +,0xA304 +,0x015E +,0xA305 +,0x015F +,0xBC20 +,0x3136 +,0xBC21 +,0x3163 +,0xBD04 +,0x04D2 +,0xFA04 +,0xFB24 +,0xFA0C +,0xFB24 +,0xBD04 +,0x04D8 +,0xFA0C +,0xFB24 +,0xBC20 +,0x31B2 +,0x7717 +,0xBA51 +,0x7006 +,0xBA14 +,0x38BC +,0x084D +,0xB048 +,0x319C +,0xA301 +,0x0266 +,0xBC20 +,0x0200 +,0xFA91 +,0xB040 +,0x0050 +,0xB060 +,0x0010 +,0xA304 +,0x0261 +,0xA300 +,0x0260 +,0xA306 +,0x0262 +,0xFA52 +,0x4044 +,0x1609 +,0x41E6 +,0x0894 +,0x1406 +,0xB4F2 +,0x0001 +,0x0B07 +,0xBC20 +,0x01F9 +,0xA302 +,0x02A7 +,0xBC40 +,0x1C01 +,0xBC40 +,0x3401 +,0x144E +,0x24A1 +,0xBC24 +,0x029A +,0xBC40 +,0x140C +,0xBC21 +,0x0267 +,0xBC22 +,0x0294 +,0xBC3C +,0x4000 +,0x6D79 +,0x640E +,0xBC3F +,0x0285 +,0xBC3B +,0x0290 +,0xBC30 +,0x2000 +,0x7000 +,0x244F +,0xBC40 +,0x6607 +,0xA31F +,0x028F +,0xA31B +,0x0293 +,0xBC40 +,0x0C9C +,0xBC40 +,0x149C +,0xBC40 +,0x151E +,0xBC40 +,0x2C80 +,0xBC40 +,0x3490 +,0xBC40 +,0x3C9A +,0xBC40 +,0x2D10 +,0xBC40 +,0x1D03 +,0x40A7 +,0xBC02 +,0x05B3 +,0xB04A +,0x0318 +,0xBC23 +,0x30FD +,0xBC22 +,0x30FF +,0xA304 +,0x0325 +,0xFA74 +,0xFA52 +,0x04F2 +,0xBC21 +,0x02E0 +,0x3589 +,0xB00E +,0x0318 +,0xA306 +,0x0312 +,0xA300 +,0x0326 +,0xBC26 +,0x30FC +,0xBC20 +,0x3102 +,0xFAD6 +,0xFA10 +,0xA306 +,0x0360 +,0x14AA +,0x1428 +,0x14EB +,0xA304 +,0x035F +,0xBC26 +,0x2021 +,0x35CD +,0xBC25 +,0x0327 +,0xBC24 +,0x07C0 +,0xBC3E +,0x7FFF +,0xBC3A +,0x0320 +,0xB012 +,0x0019 +,0xB024 +,0xFFFF +,0xB000 +,0xFFFF +,0x6D4B +,0x3BD4 +,0xA305 +,0x0354 +,0xA31E +,0x047A +,0xA31A +,0x02DC +,0xA301 +,0x0314 +,0xA307 +,0x0313 +,0xA304 +,0x0353 +,0xA302 +,0x0363 +,0xA303 +,0x0364 +,0xA300 +,0x0365 +,0xBC02 +,0x0263 +,0xBC02 +,0x07A4 +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0x700F +,0xBA10 +,0x0801 +,0x2680 +,0x8F09 +,0xBC20 +,0x2040 +,0x7008 +,0x4FD5 +,0xFA10 +,0x0801 +,0x2600 +,0x8F10 +,0xA301 +,0x0099 +,0x8D0F +,0xBC20 +,0x2008 +,0xBC21 +,0xFF7F +,0x7007 +,0x3A12 +,0x6214 +,0x4FD5 +,0xA31C +,0x0099 +,0xA31C +,0x02A7 +,0xA31E +,0x008D +,0xFB11 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0x8E00 +,0xDFD5 +,0xBC02 +,0x0474 +,0x6914 +,0x4FD5 +,0x4020 +,0xE9FE +,0xA309 +,0x008B +,0xA309 +,0x008C +,0xA300 +,0x00A0 +,0xBC00 +,0x0263 +,0xBC22 +,0x036A +,0xBC21 +,0x044C +,0x044A +,0x3509 +,0x32C0 +,0x4001 +,0x4023 +,0x8F01 +,0x8B04 +,0xE501 +,0x2680 +,0x8F02 +,0xBC22 +,0x2040 +,0x8E00 +,0xFB51 +,0xBC22 +,0x305A +,0x40BC +,0x703F +,0xBA52 +,0xBC3A +,0x0376 +,0xBC2E +,0x0399 +,0x4FEF +,0xBC28 +,0x03A8 +,0x2680 +,0x149A +,0x4270 +,0xA31E +,0x0372 +,0xA31A +,0x0375 +,0xA310 +,0x0395 +,0xA31C +,0x0396 +,0xA31C +,0x0397 +,0xA30E +,0x0398 +,0xA30F +,0x03B8 +,0xA308 +,0x03A6 +,0xA302 +,0x03A5 +,0xBC20 +,0x2040 +,0x8F01 +,0x4042 +,0xFB12 +,0xBC20 +,0x3079 +,0xBC3E +,0x03DC +,0xBC3A +,0x041A +,0xBC24 +,0x2044 +,0xFA03 +,0xBC30 +,0x03F1 +,0xA31E +,0x03DB +,0xA31A +,0x0442 +,0xA310 +,0x03F0 +,0xFB91 +,0xA301 +,0x03E2 +,0xA303 +,0x03E0 +,0xBC22 +,0x2043 +,0x8EC0 +,0xA300 +,0x03E1 +,0xFB51 +,0xE902 +,0xA200 +,0x008C +,0xA201 +,0x0082 +,0x6980 +,0x5FD5 +,0x8F16 +,0x2611 +,0x8F14 +,0x2612 +,0x8F11 +,0xBC20 +,0x201A +,0x4201 +,0xFA10 +,0x0801 +,0x2680 +,0x8F00 +,0xBC02 +,0x06A8 +,0xBC20 +,0x201F +,0xBC21 +,0x03FF +,0xFA10 +,0x0801 +,0xBC22 +,0x2002 +,0x8C06 +,0xFB50 +,0xBC20 +,0x2002 +,0xA201 +,0x0089 +,0xFB11 +,0xBC20 +,0x2000 +,0x4021 +,0xFB11 +,0xFA11 +,0x2693 +,0x8FFC +,0x8E00 +,0xBC20 +,0x2000 +,0x4001 +,0xBC22 +,0x2020 +,0x7010 +,0x3B11 +,0xFA51 +,0x0808 +,0x2600 +,0x4021 +,0x8F0C +,0xBC20 +,0x2001 +,0x8E00 +,0xFB11 +,0xFA11 +,0x2693 +,0x8FFC +,0x8E00 +,0x7000 +,0x4FD5 +,0xBC20 +,0x2001 +,0x8C02 +,0xFB11 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x201B +,0x4022 +,0xFA10 +,0x4381 +,0x0902 +,0x0841 +,0x4043 +,0x2640 +,0x0803 +,0x124B +,0xA204 +,0x0089 +,0xBC23 +,0x201D +,0x8F10 +,0x0461 +,0xFA73 +,0xA301 +,0x0089 +,0x218B +,0x8F1A +,0x2600 +,0xBC20 +,0x201C +,0x8F03 +,0xFA10 +,0x8C15 +,0xA300 +,0x0089 +,0xA302 +,0x0086 +,0x8D10 +,0xBC25 +,0x201C +,0x0061 +,0xFAB4 +,0xA301 +,0x0089 +,0x208C +,0x8F07 +,0x2600 +,0x8F03 +,0xFA70 +,0x8C04 +,0xA300 +,0x0089 +,0xA302 +,0x0086 +,0xBC20 +,0x201F +,0xBC21 +,0x03FF +,0xFA10 +,0xA203 +,0x0089 +,0x0801 +,0x2258 +,0x8F03 +,0x8EC0 +,0xA302 +,0x0086 +,0x8E00 +,0x8EB8 +,0xBC20 +,0x201B +,0x4381 +,0xFA10 +,0x0801 +,0xA201 +,0x0089 +,0xB480 +,0x0002 +,0xBC22 +,0x201C +,0x0008 +,0xFA51 +,0x2001 +,0xA300 +,0x0089 +,0x8F03 +,0x8EC0 +,0x4020 +,0xA300 +,0x0086 +,0x8EB8 +,0xE902 +,0xBC22 +,0x2000 +,0xDFD5 +,0x41A3 +,0xBC02 +,0x0723 +,0x4344 +,0xBC25 +,0x0400 +,0x2620 +,0x8F05 +,0xBC02 +,0x07F0 +,0x5404 +,0x4025 +,0xBC02 +,0x07F0 +,0x8D06 +,0xBC02 +,0x07FB +,0x5404 +,0x4025 +,0xBC02 +,0x07FB +,0xBC02 +,0x072A +,0x4E20 +,0xBC02 +,0x07B8 +,0xBC20 +,0x0001 +,0x0848 +,0xB412 +,0x0000 +,0xBC22 +,0x1000 +,0x4183 +,0xBC02 +,0x0723 +,0x220A +,0x8F3F +,0xDFE2 +,0xBC21 +,0x2098 +,0x41C2 +,0xFA33 +,0x0ADA +,0xFB33 +,0x4060 +,0x4841 +,0xBC02 +,0x07D8 +,0xBC21 +,0x2098 +,0x4202 +,0xBC20 +,0xFFFE +,0x0ADA +,0xFB33 +,0x08D8 +,0xFB33 +,0x4E20 +,0xBC02 +,0x07B8 +,0xBC22 +,0xFFFE +,0x084A +,0xCFE2 +,0x0A4A +,0xBC02 +,0x07CA +,0x4224 +,0xBC25 +,0x4000 +,0xBC02 +,0x07FB +,0x4044 +,0x4045 +,0xBC02 +,0x07FB +,0x4284 +,0x4105 +,0xBC02 +,0x07FB +,0x4284 +,0x4105 +,0xBC02 +,0x07F0 +,0xCFE0 +,0xBC02 +,0x0733 +,0x4E24 +,0x4045 +,0xBC02 +,0x07FB +,0x4E24 +,0x4045 +,0xBC02 +,0x07F0 +,0xBC20 +,0x2098 +,0x43E1 +,0xFB11 +,0x4021 +,0xFB11 +,0xBC22 +,0x4000 +,0x41C3 +,0xBC02 +,0x0723 +,0x38A2 +,0x4E20 +,0xBC02 +,0x07B8 +,0xB55A +,0x0002 +,0x0A4D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC20 +,0x201F +,0x8E00 +,0xFA10 +,0x0890 +,0x1093 +,0x8EB8 +,0xE902 +,0x4E24 +,0xDFD5 +,0x4085 +,0xBC02 +,0x07FB +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0xBC21 +,0x202D +,0xDFD5 +,0xDFE0 +,0x4280 +,0xBC02 +,0x07CA +,0xBC22 +,0x8018 +,0xBC23 +,0x8098 +,0xCFE0 +,0x2600 +,0x1853 +,0x42C0 +,0xBC02 +,0x07CA +,0x4240 +,0xBC21 +,0xE419 +,0xBC02 +,0x07CA +,0x4260 +,0xBC21 +,0x9010 +,0xBC02 +,0x07CA +,0x4040 +,0xBC21 +,0x0FFB +,0xBC02 +,0x07CA +,0x4220 +,0xBC21 +,0x2020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07D8 +,0x4220 +,0xBC21 +,0x1020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07D8 +,0x4220 +,0xBC21 +,0x4020 +,0xBC02 +,0x07CA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07D8 +,0x4520 +,0xBC21 +,0x8001 +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0xBC20 +,0x2023 +,0xDFD5 +,0xFA16 +,0xBC20 +,0x2000 +,0x09B0 +,0xDFE6 +,0x4060 +,0xBC02 +,0x07B8 +,0xBC22 +,0x39AE +,0xBC23 +,0x19AE +,0xCFE6 +,0x2660 +,0x195A +,0x220D +,0x8F02 +,0x3825 +,0xBC02 +,0x07CA +,0x4480 +,0xBC02 +,0x07B8 +,0xBC22 +,0x0000 +,0xBC23 +,0x0001 +,0xCFE6 +,0x2660 +,0x195A +,0x220D +,0x8F02 +,0x3825 +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0x4E04 +,0x4805 +,0xDFD5 +,0xBC20 +,0x2023 +,0xBC21 +,0x4000 +,0xFA10 +,0x0801 +,0x2600 +,0x8F01 +,0xBC02 +,0x07FB +,0x8D02 +,0xBC02 +,0x07F0 +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC22 +,0x209A +,0xBC23 +,0x0100 +,0x0AD8 +,0xBC21 +,0x209D +,0xFB53 +,0x4043 +,0xFA32 +,0x0893 +,0x26A0 +,0x8FFA +,0xBC22 +,0x209C +,0x8E00 +,0xFA51 +,0x8EB8 +,0xBC22 +,0x209A +,0xBC23 +,0x209B +,0xFB50 +,0xBC22 +,0x209D +,0xFB71 +,0x4023 +,0xFA51 +,0x084B +,0x2690 +,0x8FFB +,0x8EB8 +,0xBC08 +,0x07E6 +,0x8E00 +,0xBDC8 +,0x07E5 +,0x8E00 +,0xBC09 +,0x07E4 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8E00 +,0x8EB8 +,0xBC08 +,0x07EE +,0x8E00 +,0xBC09 +,0x07ED +,0x8E00 +,0x8E00 +,0x8EB8 +,0xE902 +,0x3804 +,0xDFD5 +,0xBC02 +,0x07B8 +,0x0A4D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xE902 +,0x1745 +,0xDFD5 +,0x3804 +,0xBC02 +,0x07B8 +,0x084D +,0xBC02 +,0x07CA +,0xCFD5 +,0xE9FE +,0x8EB8 +,0xBC20 +,0x201A +,0x4201 +,0xFA10 +,0x0801 +,0x2600 +,0x8F00 +,0x8EB8 +,0xE902 +,0x4020 +,0xDFD5 +,0xBC21 +,0x1F2A +,0xBC02 +,0x07CA +,0xBC20 +,0x01F4 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x402D +,0xBC02 +,0x07CA +,0x4280 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x5FED +,0xBC02 +,0x07CA +,0x4020 +,0xBC21 +,0x1F6A +,0xBC02 +,0x07CA +,0x4280 +,0x4461 +,0xBC02 +,0x07E8 +,0x4000 +,0xBC21 +,0x7FED +,0xBC02 +,0x07CA +,0x4500 +,0x4461 +,0xBC02 +,0x07E8 +,0xBC20 +,0x2023 +,0xBC22 +,0x39AE +,0xBC23 +,0x19AE +,0xFA10 +,0xBC21 +,0x2000 +,0x0841 +,0x38C1 +,0x2610 +,0x185A +,0x4060 +,0xBC02 +,0x07CA +,0x4040 +,0xBC21 +,0x0FF9 +,0xBC02 +,0x07CA +,0xBC20 +,0x000A +,0x4461 +,0xBC02 +,0x07E8 +,0x4022 +,0x4003 +,0x2660 +,0x1853 +,0x4480 +,0xBC02 +,0x07CA +,0x4540 +,0xBC02 +,0x07B8 +,0xDFE1 +,0x40C0 +,0x4202 +,0x41E3 +,0x4104 +,0xBC25 +,0x31EC +,0x41E6 +,0xBC02 +,0x08EC +,0x41C0 +,0xBC24 +,0x87FF +,0x4166 +,0xBC02 +,0x08F9 +,0xCFE1 +,0x4000 +,0x4402 +,0x43E3 +,0x4164 +,0xBC25 +,0x31ED +,0x43E6 +,0xBC02 +,0x08EC +,0xDFE5 +,0x4180 +,0xBC24 +,0xFF07 +,0x4066 +,0xBC02 +,0x08F9 +,0xCFE5 +,0x40E0 +,0xBC24 +,0xFFE0 +,0x4006 +,0xBC02 +,0x08F9 +,0x4000 +,0xBC02 +,0x0733 +,0xBC20 +,0x2098 +,0x43E1 +,0xFB11 +,0x4021 +,0xFB11 +,0x4500 +,0x4401 +,0xBC02 +,0x07CA +,0x4140 +,0xBC21 +,0x0841 +,0xBC02 +,0x07CA +,0xBC20 +,0x01F4 +,0x4841 +,0xBC02 +,0x07E8 +,0x4140 +,0xBC21 +,0x0840 +,0xBC02 +,0x07CA +,0x4500 +,0x4001 +,0xBC02 +,0x07CA +,0xBC21 +,0x2023 +,0xBC22 +,0x0400 +,0xFA31 +,0x084A +,0x2610 +,0x8F0A +,0x5364 +,0x4065 +,0xBC02 +,0x07F0 +,0x4AC0 +,0x4021 +,0xBC02 +,0x07CA +,0xBC21 +,0x1FFA +,0x8D02 +,0xBC21 +,0x1FFB +,0x4040 +,0xBC02 +,0x07CA +,0x4C80 +,0x4841 +,0xBC02 +,0x07E8 +,0x41E0 +,0xBC21 +,0x4042 +,0xBC02 +,0x07CA +,0xBC02 +,0x07A4 +,0x4E80 +,0x4021 +,0xBC02 +,0x07CA +,0x4E60 +,0xBC21 +,0x0480 +,0xBC02 +,0x07CA +,0x5380 +,0xBC21 +,0xAB40 +,0xBC02 +,0x07CA +,0x4102 +,0x4503 +,0xBC24 +,0x2023 +,0xBC25 +,0x0400 +,0xFA94 +,0x0925 +,0x2640 +,0x1853 +,0x53C0 +,0xBC02 +,0x07CA +,0x4E04 +,0x4025 +,0xBC02 +,0x07FB +,0xCFD5 +,0xE9FE +,0x8EB8 +,0x1048 +,0x0891 +,0x08D9 +,0x2620 +,0x1863 +,0xFAB2 +,0x004A +,0x4002 +,0x3210 +,0x1851 +,0x210E +,0x1971 +,0x8EB8 +,0xE901 +,0x8E00 +,0xDFF5 +,0xBC02 +,0x07B8 +,0x0861 +,0x316E +,0x0A4D +,0xBC02 +,0x07CA +,0xCFF5 +,0xE9FF +,0x8EB8 +,0xBC20 +,0x209F +,0xBC21 +,0x31DB +,0xA300 +,0x047E +,0xA301 +,0x047D +,0xBD11 +,0x0911 +,0xFA22 +,0xFB02 +,0x8EC0 +,0xA300 +,0x047E +,0xA301 +,0x047D +,0x0000 +,0x6915 +,0xA908 +,0xA21B +,0x0180 +,0xA21E +,0x017E +,0xA21D +,0x016E +,0xBC3C +,0x3116 +,0xBC30 +,0x311D +,0x7016 +,0xDF1B +,0xA204 +,0x017F +,0xA202 +,0x0181 +,0xA203 +,0x0182 +,0xA201 +,0x01AD +,0x6915 +,0x1F3D +,0x77F6 +,0x9F5E +,0xBC26 +,0x3106 +,0xDF70 +,0xDF9C +,0xBD08 +,0x09DB +,0xA200 +,0x015E +,0xBC3C +,0x009C +,0xBC3E +,0x00C2 +,0xA304 +,0x017F +,0x6E7B +,0x9FA1 +,0x6E43 +,0xBAC5 +,0x6E4B +,0xBE18 +,0x396C +,0x8A0E +,0xBF95 +,0x8A18 +,0x77E6 +,0x9FC6 +,0x6A91 +,0x7AD5 +,0x7077 +,0xFE18 +,0x6A91 +,0x4F86 +,0x88D0 +,0x6E62 +,0xFAC7 +,0x6E7A +,0x5FE0 +,0x39C8 +,0x8890 +,0xBC3D +,0x0170 +,0x6FCA +,0x4F41 +,0x6910 +,0xBAC5 +,0x6910 +,0xFF38 +,0x7016 +,0xBE38 +,0x2A47 +,0x6A91 +,0xFE38 +,0xBF95 +,0x8A38 +,0x6A91 +,0x7AC7 +,0xBF95 +,0x8A38 +,0xBF9D +,0x8E38 +,0xBF95 +,0xAA38 +,0x2A47 +,0x6A91 +,0xFE38 +,0x2A45 +,0x88D0 +,0x398B +,0x39E9 +,0x39C8 +,0x88F0 +,0xB06C +,0xFFFA +,0x613E +,0xDF86 +,0xBC26 +,0x7ADD +,0xBCB7 +,0x8000 +,0x04AA +,0xBC26 +,0x7ADD +,0xBCA5 +,0x8000 +,0xA300 +,0x015E +,0x6025 +,0x0F00 +,0x6FCB +,0xCFC4 +,0x6036 +,0x0FE0 +,0xB048 +,0xFFF1 +,0x6910 +,0xBF38 +,0x6910 +,0xDF41 +,0xFA86 +,0x6960 +,0x3E18 +,0x8A0E +,0xBF99 +,0x0C18 +,0x7076 +,0x9F07 +,0x6A91 +,0xBA96 +,0x7016 +,0xBE18 +,0x2A46 +,0x88E0 +,0x398B +,0x39E9 +,0x39C8 +,0x88F0 +,0xA300 +,0x015E +,0x7077 +,0x8F20 +,0xBC3C +,0x0160 +,0x6FCD +,0xCF66 +,0x6910 +,0xBF18 +,0x6910 +,0xFAC7 +,0x7147 +,0xFE18 +,0x2A47 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0x2A47 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0xBF9D +,0x8E18 +,0x2A47 +,0xBF9D +,0xAE18 +,0x2A47 +,0x88F0 +,0xB06C +,0xFFFA +,0x6E62 +,0xDF66 +,0x39E9 +,0x39C8 +,0x88E0 +,0x0E7A +,0x3F3E +,0x63EC +,0xFF18 +,0x6FC3 +,0x8FA1 +,0xBC3D +,0x0184 +,0xB068 +,0xFFF1 +,0x6915 +,0xBF38 +,0x6915 +,0x1F20 +,0x5FDA +,0x3885 +,0xCF1E +,0xCF50 +,0xA310 +,0x017E +,0xA301 +,0x01AD +,0xA304 +,0x017F +,0xA302 +,0x0181 +,0xA31E +,0x0180 +,0xA303 +,0x0182 +,0xCF3B +,0x8EC0 +,0xE9F8 +,0xA31B +,0x016E +,0x0000 +,0x2451 +,0xA201 +,0x01AC +,0x3909 +,0xBC22 +,0x3124 +,0x2453 +,0xBC3D +,0x0184 +,0x451F +,0xBD08 +,0x0A11 +,0x77F6 +,0xFA43 +,0x2442 +,0x6960 +,0x3E38 +,0x8A0C +,0xBF8C +,0x8638 +,0x2A43 +,0x88B0 +,0x398B +,0x39E9 +,0x39C8 +,0x88C0 +,0x439B +,0x6E18 +,0x2403 +,0xB024 +,0xFFF3 +,0x6D06 +,0xA444 +,0x6910 +,0xEA38 +,0x8EC0 +,0xA301 +,0x01AC +,0x8E00 +,0xBC20 +,0x3131 +,0xA201 +,0x02C2 +,0xFA10 +,0x2600 +,0x8F3E +,0xA200 +,0x01E2 +,0x2680 +,0x8F39 +,0x2610 +,0xA200 +,0x01BE +,0xB010 +,0xFFFF +,0x8F2C +,0xA202 +,0x01E3 +,0x26A0 +,0x8F28 +,0xBC22 +,0x02A8 +,0xBC23 +,0x3133 +,0xBC24 +,0x3132 +,0xBC40 +,0x3906 +,0xFA73 +,0xBC25 +,0x3134 +,0xBC27 +,0x3135 +,0xBC40 +,0x3102 +,0xFA94 +,0x04F3 +,0xFAB5 +,0xFAF6 +,0x04A2 +,0x1095 +,0x10DE +,0x1D1A +,0x4003 +,0x3240 +,0x3843 +,0x8F02 +,0xB228 +,0x0040 +,0x4803 +,0x18DC +,0x2103 +,0x8F05 +,0x2183 +,0x8F18 +,0x3401 +,0xA300 +,0x01BE +,0x8D15 +,0x8C14 +,0xA301 +,0x01BE +,0x3280 +,0x4002 +,0x8F0D +,0xA301 +,0x01BE +,0x8D0C +,0x8C0B +,0x4002 +,0x2690 +,0x4800 +,0x4002 +,0x8F03 +,0x8E00 +,0x8C04 +,0xA302 +,0x01BE +,0xA300 +,0x01BE +,0xA200 +,0x01BE +,0x2600 +,0xBC21 +,0x2035 +,0x4020 +,0x8EC0 +,0x1810 +,0xFB30 +,0x0000 +,0x38E0 +,0xA200 +,0x01E1 +,0xB202 +,0x0040 +,0x405A +,0xBC3C +,0x01C0 +,0x441E +,0x8F0F +,0x6E11 +,0xE800 +,0xBD08 +,0x0A88 +,0x6D74 +,0xA103 +,0xE142 +,0x1B1A +,0x0E9A +,0x3F14 +,0x6E11 +,0xFF18 +,0x8E00 +,0x8EC0 +,0xA300 +,0x01E1 +,0x8E00 +,0xB522 +,0x0009 +,0x3867 +,0xBD08 +,0x0A9D +,0x6D76 +,0xA184 +,0xE1C3 +,0xBCB6 +,0x8000 +,0x8E00 +,0x1B63 +,0x0EE3 +,0x3F1D +,0x6E19 +,0xFF18 +,0x8E00 +,0x8EC0 +,0xA300 +,0x01E1 +,0x8E00 +,0xA200 +,0x01F7 +,0x2600 +,0xA200 +,0x01E4 +,0x8F44 +,0xA201 +,0x01F8 +,0x2690 +,0x8F41 +,0xBC21 +,0x3173 +,0xA202 +,0x01E5 +,0xFA31 +,0x2191 +,0x8F02 +,0x3491 +,0xA302 +,0x01E5 +,0xA202 +,0x01E5 +,0x2251 +,0x8F33 +,0xBC21 +,0x02A8 +,0xBC23 +,0x316F +,0xBC25 +,0x316C +,0xBC40 +,0x4086 +,0xFA73 +,0xBC22 +,0x316D +,0xBC24 +,0x316E +,0x680C +,0xFAB3 +,0xFA52 +,0xFA94 +,0x38A3 +,0x8F04 +,0xBC23 +,0x3170 +,0x8E00 +,0xFA73 +,0x2033 +,0x18D4 +,0xBC26 +,0x3171 +,0xBC40 +,0x4881 +,0xFAD6 +,0x210E +,0x8F04 +,0xBC25 +,0x3172 +,0x8E00 +,0xFAB5 +,0x210D +,0x1954 +,0x1E5D +,0x2208 +,0x401E +,0x8F0A +,0x2108 +,0xA31E +,0x01E5 +,0x8F03 +,0x8E00 +,0x8C05 +,0xB000 +,0xFFFF +,0x3401 +,0x8D01 +,0x4000 +,0x40A1 +,0x2801 +,0xA300 +,0x01E4 +,0x382E +,0xB012 +,0x3136 +,0xBC20 +,0x3163 +,0xBD04 +,0x0AFB +,0xFA22 +,0xFB02 +,0xFA2A +,0xFB02 +,0xBD04 +,0x0B01 +,0xFA2A +,0xFB02 +,0x8EB8 +,0x0000 +,0x2451 +,0xA201 +,0x01E0 +,0x3909 +,0xBC22 +,0x3163 +,0x2453 +,0xBC3D +,0x01C0 +,0x441F +,0xBD08 +,0x0B25 +,0x77F6 +,0xFA43 +,0x2442 +,0x6960 +,0x3E38 +,0x8A08 +,0xBF8C +,0x8638 +,0x2A43 +,0x88B0 +,0x398B +,0x39E9 +,0x39C8 +,0x88C0 +,0x429B +,0x6E18 +,0x2403 +,0xB024 +,0xFFF7 +,0x6D06 +,0xA444 +,0x6910 +,0xEA38 +,0x8EC0 +,0xA301 +,0x01E0 +,0x8E00 +,0xBC20 +,0x31B2 +,0x5FE1 +,0xFA10 +,0xB020 +,0x319C +,0xB012 +,0x319C +,0x0008 +,0xBC23 +,0x01F9 +,0xFA10 +,0xBC40 +,0x1981 +,0x6862 +,0x3A52 +,0xBC40 +,0x3582 +,0x8F06 +,0xA200 +,0x0085 +,0x2681 +,0x8F03 +,0x8EC0 +,0x4040 +,0xA300 +,0x0085 +,0x8EB8 +,0x0000 +,0xBC21 +,0x02A8 +,0xBC23 +,0x0263 +,0xBC40 +,0x4880 +,0xBC40 +,0x5084 +,0x6E10 +,0xE580 +,0x7000 +,0x25C4 +,0xA203 +,0x0266 +,0xBC40 +,0x5881 +,0x2630 +,0xBC40 +,0x1501 +,0x401C +,0x8F28 +,0x3820 +,0xB532 +,0x0002 +,0xB036 +,0x3174 +,0x3882 +,0x6910 +,0xBA65 +,0x6960 +,0x2206 +,0x8A02 +,0xBBD4 +,0xCA86 +,0x6A3D +,0x7A73 +,0x88C0 +,0x3215 +,0x00E3 +,0x8F05 +,0xB416 +,0x0002 +,0x0441 +,0x3214 +,0x1801 +,0x8C0A +,0x3B80 +,0x3330 +,0x8F04 +,0x2614 +,0x8F04 +,0x8E00 +,0x8CE1 +,0x3449 +,0x344D +,0x8DDE +,0xBC20 +,0x31B2 +,0x383C +,0xFA10 +,0x2108 +,0x1801 +,0xB000 +,0x319C +,0x8EC0 +,0xFA10 +,0xA300 +,0x01FF +,0xBC25 +,0x01F9 +,0x34AB +,0xE904 +,0xE143 +,0x6122 +,0xDF82 +,0x3320 +,0x8F02 +,0xBC23 +,0x31B4 +,0x8C05 +,0xFA73 +,0xBC23 +,0x31B3 +,0x8E00 +,0xFA73 +,0x2813 +,0xA201 +,0x0260 +,0xBC40 +,0x268E +,0xBC40 +,0x2E8F +,0x6D4A +,0xA29E +,0x700E +,0xE2DC +,0x7307 +,0xDFDE +,0x6E7F +,0x224C +,0xCFCE +,0x6A34 +,0xDFA5 +,0x6E28 +,0x2800 +,0xBC3D +,0x0200 +,0x6EE3 +,0xE287 +,0x88E0 +,0xBD07 +,0x0BC7 +,0x6D00 +,0x9FCE +,0xBCFF +,0x8000 +,0x8E00 +,0xE4E7 +,0xE2C5 +,0xBCDB +,0x8000 +,0x6E7F +,0x0FCE +,0x6A34 +,0xE4E5 +,0x38A0 +,0x88E0 +,0x6EE3 +,0xE287 +,0xDFCE +,0xBCFF +,0x8000 +,0xCF82 +,0xE4E7 +,0xE2C5 +,0xBCDB +,0x8000 +,0xE64C +,0xE4E5 +,0xCFDF +,0xE546 +,0xA301 +,0x0260 +,0xA31F +,0x01F9 +,0xCFA3 +,0x8EC0 +,0xE9FC +,0xE5DC +,0x0000 +,0xBC22 +,0x31B7 +,0x8E00 +,0xFA52 +,0x26A0 +,0x8F04 +,0x8EC0 +,0xBC22 +,0x6568 +,0xA302 +,0x0268 +,0xA200 +,0x0261 +,0x403A +,0xBC3C +,0x0200 +,0x4C1E +,0x8E00 +,0xE062 +,0xA300 +,0x0261 +,0x6904 +,0xBC1B +,0x241B +,0xBD1E +,0x0BFA +,0x67A6 +,0xBC1B +,0x241B +,0x1E9A +,0xBC3D +,0x0290 +,0xA201 +,0x0293 +,0x3B7A +,0x407F +,0xBC23 +,0x31B6 +,0x6EE7 +,0x64E2 +,0xFA73 +,0xA204 +,0x02B0 +,0xA300 +,0x0261 +,0xA301 +,0x0293 +,0x21A3 +,0x8F2C +,0xA200 +,0x0293 +,0x407E +,0xBC23 +,0x31B5 +,0x7016 +,0xBC1C +,0x1EA2 +,0xB800 +,0xE61C +,0x1EA2 +,0x1E93 +,0xB124 +,0x0001 +,0xBC23 +,0x2000 +,0xBCA4 +,0xC000 +,0xBC24 +,0x3FFF +,0x24DA +,0xB056 +,0xFFFF +,0x3095 +,0x0562 +,0xA300 +,0x0293 +,0x4004 +,0xBD0B +,0x0C39 +,0x33D0 +,0xB56A +,0x0001 +,0x8F02 +,0xB548 +,0x0001 +,0x8C05 +,0x0172 +,0x3521 +,0x0572 +,0xB548 +,0x0001 +,0x8E00 +,0x30A3 +,0xA302 +,0x0269 +,0xA202 +,0x0269 +,0xA203 +,0x0268 +,0x0493 +,0x3220 +,0xBC23 +,0x0400 +,0x8F02 +,0xBC23 +,0x31B8 +,0x8E00 +,0xFA73 +,0xBC24 +,0x0267 +,0x281A +,0xE643 +,0x8EC0 +,0xBC40 +,0x260F +,0xBC40 +,0x1E0E +,0x0000 +,0xBC23 +,0x0267 +,0x349D +,0xE904 +,0x6D57 +,0xA15F +,0x6D27 +,0xDF82 +,0x700E +,0xA2DD +,0xBC40 +,0x2184 +,0x6E7F +,0x5FDF +,0xBC40 +,0x1983 +,0x7307 +,0xA14C +,0xCFCE +,0x6AA7 +,0x1FA5 +,0xA200 +,0x0262 +,0xBC3C +,0x0200 +,0x88E0 +,0x6EEB +,0xFC1F +,0x6960 +,0x1FCE +,0xBC25 +,0x026F +,0xBCFD +,0xC000 +,0xBD07 +,0x0C8C +,0xB51E +,0x0002 +,0x6D7A +,0xA681 +,0xE061 +,0xBC9C +,0x4000 +,0x6E7F +,0x4FCE +,0xB512 +,0x0002 +,0x6AA7 +,0x26C1 +,0x88E0 +,0x6E29 +,0xDFCE +,0x6EEB +,0xFC1F +,0xBCFD +,0xC000 +,0x8E00 +,0xB51E +,0x0002 +,0xE681 +,0xE061 +,0xBC9C +,0x4000 +,0xCFA3 +,0xB512 +,0x0002 +,0xBC24 +,0x0267 +,0xE6C1 +,0xE5DD +,0xE54C +,0xA300 +,0x0262 +,0xBC40 +,0x0E06 +,0xCF85 +,0xCFDE +,0x8EC0 +,0xE9FC +,0xE6DE +,0xA200 +,0x02A7 +,0x2600 +,0xBC01 +,0x0D4B +,0xA203 +,0x0294 +,0x2630 +,0xA202 +,0x02C5 +,0xBC25 +,0x1000 +,0xA200 +,0x02C6 +,0xA204 +,0x02C3 +,0xA201 +,0x01BE +,0xBCA5 +,0x4000 +,0xBC23 +,0x0294 +,0x8F33 +,0xBC26 +,0x31CE +,0xBC40 +,0x1185 +,0x6990 +,0x7AD4 +,0x0495 +,0xBCA5 +,0x0000 +,0xBC26 +,0x31CF +,0x00AA +,0xBC25 +,0x31D0 +,0xBC40 +,0x1984 +,0xBC40 +,0x2187 +,0x0404 +,0xFAD6 +,0x044F +,0xFAB5 +,0xBC81 +,0x8000 +,0xBC93 +,0x4000 +,0x0020 +,0x0079 +,0xA204 +,0x0299 +,0xBC40 +,0x1582 +,0xBC40 +,0x1D80 +,0xBC40 +,0x2581 +,0x8F07 +,0x32C0 +,0x4000 +,0x8F00 +,0xB008 +,0xFFFF +,0x8C13 +,0xA300 +,0x0299 +,0xBC20 +,0x4000 +,0x21A0 +,0x8F00 +,0x3421 +,0x8C0B +,0xA300 +,0x0299 +,0x403E +,0xBC40 +,0x1D80 +,0xA31E +,0x0294 +,0xBC40 +,0x2581 +,0xBC40 +,0x1582 +,0xBC20 +,0x31D1 +,0xBC40 +,0x1185 +,0xFA10 +,0x20A8 +,0x4020 +,0xBC40 +,0x1981 +,0x3840 +,0x8F06 +,0xBC20 +,0x31D2 +,0x8E00 +,0xFA10 +,0x2088 +,0x3802 +,0x8F00 +,0x4000 +,0xBC24 +,0x31D3 +,0xBC40 +,0x2183 +,0xFA94 +,0xBC27 +,0x31EE +,0x4006 +,0x6867 +,0x3AF3 +,0x1932 +,0x202B +,0x8F04 +,0xBC23 +,0x31EF +,0x8E00 +,0xFA73 +,0x218B +,0x8F00 +,0x3886 +,0x2640 +,0xBC21 +,0x029A +,0x8F0B +,0xBC23 +,0x31D4 +,0xA204 +,0x0299 +,0xFA73 +,0x2023 +,0x8F01 +,0x2600 +,0x8F03 +,0x8E00 +,0x8C13 +,0xA306 +,0x0295 +,0xBC20 +,0x31F7 +,0xBC40 +,0x2083 +,0xFA10 +,0x2118 +,0x1803 +,0xA302 +,0x0295 +,0xBC40 +,0x1C86 +,0xBC40 +,0x1486 +,0xBC40 +,0x5C86 +,0xBC40 +,0x2480 +,0xBC40 +,0x2080 +,0xB230 +,0x7530 +,0x4C02 +,0x8EC0 +,0x1810 +,0xBC40 +,0x2480 +,0x8EC0 +,0x4000 +,0xA300 +,0x0294 +,0x0000 +,0xBC22 +,0x31F0 +,0xE91C +,0xBC24 +,0x029A +,0x7007 +,0x3A52 +,0x6E11 +,0x1C82 +,0x6E7F +,0x3C85 +,0xBC26 +,0x31F4 +,0xBC23 +,0x31F3 +,0x77FE +,0xDCA4 +,0xBC27 +,0x31F2 +,0xB801 +,0xA891 +,0x7027 +,0xFA73 +,0xFAF6 +,0xDCC3 +,0xBC27 +,0x31D5 +,0xBC23 +,0x31DA +,0xDD26 +,0xDD04 +,0xFAF6 +,0xBC24 +,0x31F5 +,0xFA73 +,0xDD66 +,0xDD43 +,0xFA96 +,0xB074 +,0x000B +,0xBC23 +,0x31D8 +,0xDDA6 +,0xDD87 +,0xBC26 +,0x31D7 +,0xB800 +,0xE6F7 +,0xDCE1 +,0xBC24 +,0x31D6 +,0x6D34 +,0x9DC3 +,0xDDE7 +,0xBC21 +,0x8000 +,0xFAD6 +,0xBC27 +,0x31D9 +,0xFA94 +,0x6163 +,0x9E46 +,0xE1DE +,0x6D34 +,0xDE03 +,0x6143 +,0x1E24 +,0xDE86 +,0xDE63 +,0xB801 +,0xEE73 +,0xB064 +,0x000C +,0xBC21 +,0x31F6 +,0xDEA7 +,0xDEE3 +,0xDF06 +,0xBC27 +,0x31F1 +,0xB034 +,0x0009 +,0x6D45 +,0x1EC4 +,0xB800 +,0x6CD1 +,0x6E81 +,0xBAF6 +,0xB024 +,0x000A +,0xDFA6 +,0xDF42 +,0xDF23 +,0xE1C3 +,0xE142 +,0xE246 +,0xDF64 +,0xDF8F +,0xBC3D +,0x029F +,0xBD08 +,0x0E56 +,0x6CD8 +,0x1FC1 +,0x7003 +,0x0E27 +,0x6915 +,0xA044 +,0x8F01 +,0x2640 +,0x8F6F +,0x6A3B +,0xCCE5 +,0x6D6C +,0x4EC7 +,0x6A3B +,0xDFE6 +,0x88D0 +,0xB20C +,0x0060 +,0xDCE5 +,0xCDC5 +,0x8F65 +,0x6A09 +,0x4D65 +,0x88FC +,0x6910 +,0x8C86 +,0x28DD +,0x28FD +,0x8890 +,0xBCFF +,0xC000 +,0xBC92 +,0x4000 +,0x2442 +,0x28D5 +,0x6A3F +,0x4CE5 +,0x88F0 +,0x686B +,0x8D26 +,0x611E +,0x4DE7 +,0x2409 +,0x8F05 +,0xCFA6 +,0x686B +,0x8CC5 +,0xCD06 +,0x666B +,0x8CE5 +,0x6113 +,0x5DFC +,0x2409 +,0x32F0 +,0xBCEC +,0x4000 +,0x8F05 +,0xCD41 +,0x686E +,0x5DFC +,0x8F01 +,0x35F9 +,0xDDE7 +,0x686D +,0x4EE6 +,0x401F +,0x8F12 +,0x6CB8 +,0x0DC5 +,0x3BBC +,0x8F09 +,0x38FE +,0xBC21 +,0x2666 +,0xBCFE +,0x4000 +,0xB06C +,0xFFFF +,0x3BA6 +,0x3BE7 +,0x0F27 +,0x6EF7 +,0xDEFD +,0xBC3D +,0x029F +,0x8C26 +,0x409F +,0xCDE5 +,0x69B4 +,0x0EA6 +,0x8F01 +,0x3569 +,0xDDE5 +,0x684B +,0x9EFC +,0x7027 +,0xCDC5 +,0xBC3D +,0x029F +,0x8F16 +,0x6910 +,0x8FC1 +,0x5BE5 +,0x28E5 +,0xBC25 +,0x31CA +,0x403B +,0xFAA6 +,0xE0E7 +,0x8A03 +,0xBBF9 +,0x4C3F +,0x6A3F +,0x9EF0 +,0x88D0 +,0x77FE +,0xDFC1 +,0x66EB +,0x0DC5 +,0x0F26 +,0x3BC6 +,0x8D02 +,0xDFE6 +,0xCDC5 +,0x6A09 +,0x4E47 +,0x88EC +,0x6915 +,0x0F8F +,0x6915 +,0x8E85 +,0x28F7 +,0x28DD +,0x88B0 +,0xBC9D +,0x8000 +,0xBCE6 +,0xC000 +,0x6915 +,0x0F8F +,0x2456 +,0x6A33 +,0xCFC1 +,0x28D5 +,0x88A0 +,0x8E00 +,0x0556 +,0x242D +,0x26D0 +,0x8F04 +,0xCFE6 +,0xCDA7 +,0x2137 +,0x19BE +,0xDFE6 +,0x6D00 +,0xA444 +,0x6915 +,0xEA38 +,0xE4C4 +,0xCFE6 +,0xCF44 +,0xCF27 +,0xCF00 +,0xE7C3 +,0xE642 +,0xA305 +,0x029A +,0xCE02 +,0xCD83 +,0xCF65 +,0xE441 +,0xCDE7 +,0xCE64 +,0xCEFB +,0xCCF0 +,0xCCA1 +,0xE9E4 +,0xE6C6 +,0xE5C7 +,0xE55E +,0x8EC0 +,0xE65B +,0xE4D0 +,0xBC21 +,0x02A8 +,0xE90E +,0x6E18 +,0x7C22 +,0xA204 +,0x02C4 +,0x6C28 +,0xA0C5 +,0xA200 +,0x02C2 +,0x6C49 +,0x5F04 +,0xB050 +,0x31BD +,0x6E0D +,0x1F55 +,0x6980 +,0x3AB6 +,0xB012 +,0xFFF2 +,0xA21E +,0x02C6 +,0xB000 +,0x31BF +,0x616C +,0xA4DE +,0x7000 +,0x5F21 +,0xFA12 +,0x4025 +,0x180D +,0x0554 +,0xB020 +,0x31BB +,0xA204 +,0x02C5 +,0xBC40 +,0x2187 +,0x31E7 +,0xFA52 +,0x0497 +,0xB000 +,0x31B9 +,0xBC40 +,0x1987 +,0x3127 +,0x6C88 +,0x3A10 +,0x0504 +,0x38F4 +,0xB00E +,0xFFF7 +,0x6622 +,0x9F60 +,0x6D37 +,0x6446 +,0xB06E +,0xFFF6 +,0x6C90 +,0x1F86 +,0x6643 +,0x2745 +,0xB05E +,0xFFF5 +,0xB07E +,0xFFF4 +,0xE1C6 +,0x6998 +,0x66C4 +,0xE7C2 +,0xDFC7 +,0xDFA5 +,0x8F54 +,0xBC20 +,0x02A8 +,0x700F +,0x8E44 +,0x65E3 +,0x0EC5 +,0xB5A8 +,0x000F +,0x65B3 +,0x65DE +,0xBC40 +,0xBC02 +,0xBC40 +,0x5404 +,0xB4AA +,0x0001 +,0xB5B6 +,0x000F +,0xB4C8 +,0x0001 +,0xB5EC +,0x000F +,0x62B6 +,0x8EA2 +,0x0BB4 +,0x170A +,0xBC40 +,0xC406 +,0xB4E4 +,0x0001 +,0xB5C8 +,0x000F +,0xBC40 +,0x9403 +,0x62C9 +,0x8E83 +,0x178B +,0xB4F6 +,0x0001 +,0xB5EC +,0x000F +,0x0BB7 +,0xBC40 +,0x8404 +,0xCEE4 +,0xB5FA +,0x000F +,0xBC40 +,0x4405 +,0x174C +,0xBC40 +,0x8C07 +,0xB4F8 +,0x0001 +,0xB5DA +,0x000F +,0xBC40 +,0x3C02 +,0xBC40 +,0x4C03 +,0xB5A4 +,0x000F +,0xB5B6 +,0x000F +,0xBC40 +,0x3404 +,0x0B6F +,0xB5C8 +,0x000F +,0xBC40 +,0x7C02 +,0xBC40 +,0x9C03 +,0xBC40 +,0x5C01 +,0xBC40 +,0xAC01 +,0xBC40 +,0xB401 +,0xBC40 +,0x7405 +,0xBC40 +,0xA406 +,0x8C69 +,0xA304 +,0x02B5 +,0xBC23 +,0x02B5 +,0xBC22 +,0x31C4 +,0xB046 +,0xFFF9 +,0xFA52 +,0xDFE4 +,0xBC02 +,0x1E36 +,0x7000 +,0x4FE0 +,0xB030 +,0x000B +,0xBC20 +,0x31C3 +,0xB046 +,0xFFF7 +,0xFA12 +,0xCF80 +,0xDF84 +,0xBC02 +,0x1E36 +,0x7000 +,0x4F80 +,0x6D31 +,0xCFA0 +,0xBC22 +,0x31C6 +,0xB046 +,0xFFF8 +,0xFA52 +,0xDF84 +,0xBC02 +,0x1E36 +,0x7000 +,0x4F80 +,0xB030 +,0x000C +,0xBC20 +,0x31C5 +,0xB046 +,0xFFF6 +,0xFA12 +,0xCFC0 +,0xDF84 +,0xBC02 +,0x1E36 +,0x6E05 +,0x0F81 +,0xB032 +,0x000E +,0xBC40 +,0x788F +,0x7000 +,0x61CE +,0xB040 +,0xFFF3 +,0x88D8 +,0xBC22 +,0x31C7 +,0xB066 +,0xFFF3 +,0xCF20 +,0xFA52 +,0xDE65 +,0xDF26 +,0xDF83 +,0xBC02 +,0x1E36 +,0xCF80 +,0xCF01 +,0xBC47 +,0xA803 +,0xBC47 +,0x5804 +,0x6112 +,0xCE7E +,0x6C33 +,0x0F21 +,0x241B +,0xBC47 +,0xA004 +,0x6847 +,0x24DE +,0xDEE3 +,0x8F03 +,0xBC23 +,0x31C9 +,0x4001 +,0x8C05 +,0xFA72 +,0xBC23 +,0x31C8 +,0x4001 +,0xFA72 +,0xB030 +,0xFFFE +,0xB046 +,0xFFF6 +,0xCF60 +,0xBC02 +,0x1E36 +,0xBC21 +,0x02A8 +,0xBC20 +,0x31C1 +,0xCF1E +,0xBC40 +,0x4083 +,0xFA10 +,0xBC40 +,0x649E +,0x2098 +,0x8F09 +,0xBC20 +,0x31C2 +,0xBC40 +,0x5083 +,0xFA10 +,0x6406 +,0x0F55 +,0x0018 +,0x8C03 +,0xBC40 +,0x5480 +,0xCF55 +,0x8E00 +,0x8EC0 +,0xE9F2 +,0x8E00 +,0xBC23 +,0x00A5 +,0xBC20 +,0x3054 +,0x6E10 +,0xE181 +,0xB800 +,0x2074 +,0x24A1 +,0xA201 +,0x045F +,0x28C8 +,0x6911 +,0x2902 +,0xBC21 +,0x00A3 +,0x6E10 +,0x654E +,0xBC24 +,0x2081 +,0xE085 +,0xBC26 +,0x2083 +,0xB801 +,0x2837 +,0x692F +,0x65CF +,0xDFC3 +,0xFAD3 +,0x28D8 +,0x2444 +,0xBC23 +,0x00A1 +,0x6E10 +,0xE54E +,0xE185 +,0xE1C6 +,0x692D +,0x64CF +,0x28E0 +,0x2444 +,0xA200 +,0x00A0 +,0x7008 +,0xA54E +,0x6220 +,0xA5CF +,0xBC24 +,0x2080 +,0x26A0 +,0xFA94 +,0xBC22 +,0x00A7 +,0x8F0E +,0x38A2 +,0x8E00 +,0xE286 +,0xE2C7 +,0x24BE +,0xBC26 +,0x3055 +,0x8E00 +,0xFAD6 +,0x28E6 +,0x2444 +,0x8E00 +,0xA30E +,0x00A7 +,0xE6CF +,0xBC24 +,0x3053 +,0x8E00 +,0xFA94 +,0x2244 +,0x8F3A +,0x7007 +,0x8FC4 +,0xA20E +,0x00A5 +,0xE24F +,0x88C8 +,0xA20E +,0x00A1 +,0x690B +,0x21CF +,0x88B8 +,0xA20E +,0x00A3 +,0xE0CF +,0x8898 +,0xBC26 +,0x3056 +,0xE10E +,0xFAD6 +,0x6807 +,0xA14F +,0x88A8 +,0x8F10 +,0xBC26 +,0x3057 +,0x8E00 +,0xFAD6 +,0x200E +,0x8F0A +,0xBC26 +,0x3059 +,0x8E00 +,0xFAD6 +,0x212E +,0x8F04 +,0xBC25 +,0x3058 +,0x8E00 +,0xFAB5 +,0x2095 +,0x8F03 +,0x8E00 +,0x8C06 +,0xA31E +,0x008C +,0x403E +,0x8E00 +,0xA31E +,0x008C +,0x403C +,0xA303 +,0x009C +,0xA301 +,0x009D +,0xA304 +,0x009E +,0xA302 +,0x009F +,0xA31C +,0x008B +,0xE9FE +,0x8EC0 +,0x3401 +,0xA300 +,0x00A0 +,0x6C84 +,0xA904 +,0xFA13 +,0x6E0D +,0x1FD5 +,0xBC22 +,0x3104 +,0xB002 +,0xFFFD +,0xFA52 +,0xBC21 +,0x7FFF +,0x6622 +,0xA443 +,0x40A1 +,0xBC23 +,0x02CE +,0xBC24 +,0x045A +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xE906 +,0xA202 +,0x02D3 +,0x6E0D +,0x1F81 +,0xB012 +,0xFFFB +,0x6988 +,0x5FA1 +,0xDFD5 +,0x8F04 +,0xBC20 +,0x2080 +,0x4021 +,0x8C0F +,0xA301 +,0x02D3 +,0xFA11 +,0xBC02 +,0x1E46 +,0xA201 +,0x0474 +,0x1A41 +,0x7007 +,0x9F61 +,0xBC20 +,0x2080 +,0xA31E +,0x02D3 +,0xFB11 +,0x7040 +,0x4F83 +,0xBC22 +,0x3104 +,0x6C8C +,0xBA10 +,0xFA52 +,0xBC23 +,0x7FFF +,0x6626 +,0x9F60 +,0xCFA0 +,0xBC23 +,0x02D1 +,0xBC24 +,0x045B +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FA +,0x8E00 +,0xE902 +,0xFA31 +,0xDFC0 +,0xDFF5 +,0xBC02 +,0x1E46 +,0xCFC1 +,0xDFC0 +,0xFA31 +,0xBC02 +,0x1E46 +,0xCFC1 +,0x1A48 +,0xA200 +,0x02D5 +,0xA202 +,0x045C +,0x0E41 +,0x26A0 +,0xA301 +,0x02D5 +,0x8F06 +,0xBC21 +,0x2082 +,0x401E +,0xA200 +,0x02D5 +,0xA31E +,0x02D5 +,0xFB30 +,0x6D14 +,0x4FF5 +,0xE9FE +,0x40E0 +,0x8EC0 +,0x0848 +,0xA301 +,0x045C +,0x6C84 +,0xBA10 +,0xE904 +,0xB580 +,0x0002 +,0xA201 +,0x0474 +,0xB100 +,0x00BE +,0xBC23 +,0x2081 +,0x66C2 +,0x1FD5 +,0xBC22 +,0x3104 +,0x6E2D +,0x3B74 +,0xB00A +,0xFFFD +,0xFA52 +,0xBC23 +,0x7FFF +,0x6626 +,0xA444 +,0x40C1 +,0xBC23 +,0x02D6 +,0xBC24 +,0x045D +,0xBC02 +,0x1E36 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xE904 +,0xFA10 +,0x6E08 +,0x1FC1 +,0xDFF5 +,0xBC02 +,0x1E46 +,0xA201 +,0x0474 +,0xBC22 +,0x3104 +,0x6692 +,0x0FC0 +,0xBC23 +,0x2083 +,0x6C80 +,0xBA52 +,0xBC24 +,0x7FFF +,0x6E05 +,0x3B71 +,0x6628 +,0x9FA1 +,0xB000 +,0xFFFD +,0x40E1 +,0xBC23 +,0x02D9 +,0xBC24 +,0x045E +,0xBC02 +,0x1E36 +,0xCFF5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0x0000 +,0xBC21 +,0x00A9 +,0x4402 +,0xE083 +,0xE0C4 +,0x24A3 +,0xBC23 +,0x213F +,0x8E00 +,0x6960 +,0x3A74 +,0x8A0E +,0x6A38 +,0xBA74 +,0xB300 +,0x0044 +,0x28E2 +,0x8F0B +,0x2600 +,0x8F04 +,0x2444 +,0x8EC0 +,0xA30E +,0x00A9 +,0xE4CF +,0x4000 +,0x8EC0 +,0xA300 +,0x00A9 +,0xE4C0 +,0x8880 +,0x8EC0 +,0x8E00 +,0xA300 +,0x045F +,0xE904 +,0xBC21 +,0x2022 +,0x6E05 +,0x1FD5 +,0xA21C +,0x047A +,0xB000 +,0xFFFD +,0xFA35 +,0x7000 +,0x6445 +,0xDFFC +,0xBC22 +,0x0780 +,0xBC23 +,0x02DD +,0xBC24 +,0x02DF +,0xBC02 +,0x1E36 +,0xA201 +,0x02DF +,0xA200 +,0x02DC +,0xCFE2 +,0xA092 +,0x8000 +,0xB000 +,0xFFFF +,0xA301 +,0x047A +,0x2680 +,0xA300 +,0x02DC +,0x8F34 +,0xBC20 +,0x304D +,0xBC3E +,0x0320 +,0xBC3A +,0x7FFF +,0xFA10 +,0xA202 +,0x047C +,0xA31E +,0x02DC +,0xA31A +,0x047A +,0x21C8 +,0x8F14 +,0xBC20 +,0x304E +,0xBC23 +,0x304F +,0xFA10 +,0x6872 +,0x3A70 +,0x8F03 +,0x2048 +,0x8F01 +,0x26A0 +,0x8F05 +,0x21C8 +,0x8F0A +,0x4000 +,0xA300 +,0x047C +,0x8D07 +,0x4040 +,0x8C05 +,0xA300 +,0x047C +,0x4020 +,0xA300 +,0x047C +,0xA200 +,0x047C +,0x2242 +,0x4000 +,0x8F02 +,0xA300 +,0x047B +,0x8C07 +,0xCFD5 +,0x7008 +,0x0FD5 +,0x8C03 +,0xA300 +,0x047B +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FC +,0x8E00 +,0xBC20 +,0x2021 +,0xA201 +,0x047C +,0x6984 +,0x3A12 +,0x8F1B +,0x2611 +,0xB034 +,0xFFE0 +,0x8F10 +,0x2692 +,0x8F1B +,0xBC21 +,0x3051 +,0x8E00 +,0xFA31 +,0x20D1 +,0x8F00 +,0xA026 +,0x4000 +,0x21D1 +,0x8F11 +,0xB024 +,0x0020 +,0xA0A4 +,0x4000 +,0x8D0E +,0xBC21 +,0x3052 +,0x8E00 +,0xFA31 +,0x8C09 +,0xA026 +,0x4000 +,0xBC21 +,0x3050 +,0xB024 +,0x0020 +,0xFA31 +,0xA0A4 +,0x4000 +,0x8EC0 +,0xFB12 +,0x8E00 +,0x0000 +,0xBC22 +,0x3105 +,0xE902 +,0xA21C +,0x0326 +,0x77FE +,0xBA52 +,0x6EF0 +,0x9FDC +,0xA200 +,0x0312 +,0xBC3C +,0x02E0 +,0xBC22 +,0x30C2 +,0xBC23 +,0x8EE4 +,0xBC24 +,0x771E +,0xBC25 +,0x88E2 +,0x403B +,0x706F +,0xE800 +,0xBD05 +,0x11DA +,0x6E30 +,0xBC19 +,0x2442 +,0x6960 +,0x3AC7 +,0x8A08 +,0xBB3D +,0x8E19 +,0x28CF +,0xA207 +,0x0315 +,0xBC21 +,0x12EB +,0xA206 +,0x0316 +,0x28F9 +,0x28F3 +,0xA307 +,0x0316 +,0x88F0 +,0x2442 +,0x28FC +,0x28F5 +,0xA307 +,0x0315 +,0x417A +,0x88E0 +,0xA207 +,0x0317 +,0x699C +,0xEA18 +,0x2442 +,0x4001 +,0x8F00 +,0xB01E +,0xFFFF +,0x6A3C +,0x4FC1 +,0x88E4 +,0xBC3D +,0x0318 +,0x5FFA +,0x7007 +,0x64E6 +,0xA206 +,0x0317 +,0x6998 +,0xDFC1 +,0x8F02 +,0x35B1 +,0x3BA6 +,0x8E00 +,0xA31D +,0x0317 +,0xA300 +,0x0312 +,0xCFC2 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0326 +,0x0000 +,0xA200 +,0x0325 +,0xA201 +,0x0354 +,0xBC3D +,0x0327 +,0x459F +,0x403B +,0xBC3C +,0x0318 +,0x41BE +,0xBC22 +,0x30CB +,0xBD05 +,0x1200 +,0x5FFA +,0x3862 +,0x6910 +,0xBC1D +,0x6960 +,0x3A64 +,0x8A03 +,0xBBB0 +,0xC81D +,0x28EC +,0x88B0 +,0x40DA +,0xE4E3 +,0xEA18 +,0xA300 +,0x0325 +,0xA200 +,0x0353 +,0x3B9D +,0x459E +,0xBC22 +,0x30CF +,0x5FFA +,0xA301 +,0x0354 +,0x6910 +,0xBA43 +,0xE064 +,0x8A27 +,0xBB8C +,0x861C +,0x403A +,0x28E3 +,0x88A0 +,0xEA18 +,0x8EC0 +,0xA300 +,0x0353 +,0xA302 +,0x0355 +,0xBC25 +,0x0357 +,0xBC22 +,0x30F8 +,0x6E09 +,0x7CA4 +,0xB800 +,0xA6B6 +,0x24B4 +,0xA206 +,0x0356 +,0x33B0 +,0x4FE4 +,0xBC27 +,0x01FF +,0x35B1 +,0x1927 +,0x09F4 +,0xBC24 +,0x0100 +,0x4806 +,0x1926 +,0xA206 +,0x0355 +,0x2670 +,0xA307 +,0x0356 +,0x243E +,0x28FC +,0x2444 +,0x4004 +,0x7008 +,0x64CE +,0x6673 +,0x26CF +,0x2670 +,0x8F2C +,0xBC27 +,0x30F7 +,0xE2CF +,0xFAF7 +,0x6CDC +,0x26C4 +,0xA20E +,0x0357 +,0xA304 +,0x0357 +,0x88D8 +,0x8F1C +,0x3230 +,0x8F01 +,0xB036 +,0xFFFF +,0xFB53 +,0xA202 +,0x0359 +,0x2620 +,0x8F0D +,0x2622 +,0x4043 +,0x8F05 +,0xB20A +,0x099A +,0x189A +,0xB22A +,0x21EC +,0x8C08 +,0x18A2 +,0xB22A +,0x13D7 +,0x8C04 +,0x188A +,0xB20A +,0x17AE +,0x188A +,0x8C07 +,0xA302 +,0x0359 +,0xBC22 +,0x30F7 +,0xB03E +,0xFFFF +,0xFB53 +,0xA202 +,0x0359 +,0x144A +,0x2442 +,0x28F1 +,0x8894 +,0x8EC0 +,0x8E00 +,0xE441 +,0xBC22 +,0x2131 +,0xBC23 +,0x00B0 +,0xBC24 +,0x2135 +,0x6915 +,0x3B53 +,0xFA93 +,0xBC22 +,0x2136 +,0xE4C3 +,0xB800 +,0xA210 +,0xBC80 +,0x4000 +,0x6915 +,0xE902 +,0xBC21 +,0x30F9 +,0xA203 +,0x035B +,0xBC22 +,0x035C +,0x6E73 +,0xFA31 +,0xBC24 +,0x30FA +,0x28C1 +,0xA300 +,0x035B +,0xFA94 +,0x6E08 +,0xBC40 +,0x6A37 +,0x2143 +,0x2A83 +,0x88C0 +,0xDFCE +,0xDFEF +,0xBC20 +,0x0A30 +,0xBC88 +,0x0000 +,0xCFCE +,0xA300 +,0x035A +,0xCFEF +,0x2444 +,0xA203 +,0x035E +,0xB580 +,0x0001 +,0x6000 +,0xE4CE +,0xB000 +,0x2000 +,0xE54F +,0xA300 +,0x035E +,0xBC21 +,0x3244 +,0xBC80 +,0x4000 +,0xBC21 +,0x2111 +,0x8EC0 +,0xE9FE +,0xFB30 +,0xBC22 +,0x3105 +,0xBC24 +,0x30FB +,0xE906 +,0xA203 +,0x035A +,0xBC25 +,0xF000 +,0xFA52 +,0xFA94 +,0xA21E +,0x0314 +,0xA21C +,0x015F +,0x66BA +,0xDF84 +,0xDFA2 +,0x7050 +,0xDF63 +,0xDFDC +,0xDF5E +,0xBC22 +,0x0CCD +,0xBC24 +,0x2131 +,0xBC25 +,0x199A +,0xBC3B +,0x009C +,0xBC3D +,0x02E0 +,0xBD0A +,0x131D +,0xA206 +,0x035F +,0x700E +,0x8F67 +,0x63ED +,0xCFBE +,0xB47C +,0x000E +,0xB11E +,0x0005 +,0xA200 +,0x0360 +,0x0E08 +,0x2810 +,0xB5FE +,0x000E +,0x380E +,0x1BB7 +,0xB000 +,0x0400 +,0xBCF0 +,0xC000 +,0xA306 +,0x035F +,0xBCED +,0x4000 +,0x283A +,0xA307 +,0x0360 +,0x888C +,0xBC27 +,0x00B1 +,0x6EE7 +,0x7B97 +,0x606C +,0x0F40 +,0xBC27 +,0x3244 +,0xBCED +,0xC000 +,0x7016 +,0xBC1F +,0x6EE6 +,0xDF40 +,0xBC20 +,0x2135 +,0xBC21 +,0x2111 +,0xFA10 +,0xBC8E +,0x0000 +,0xFB36 +,0xB560 +,0x0001 +,0xCF80 +,0xBC8C +,0x0000 +,0xBC3E +,0x00C2 +,0x63E1 +,0x8FC0 +,0x3F3E +,0xFF18 +,0xDFC0 +,0xCFC2 +,0xA302 +,0x015F +,0xCF43 +,0x8EC0 +,0xE9FA +,0xA303 +,0x0314 +,0xA203 +,0x0366 +,0x6D06 +,0x6044 +,0xBC22 +,0x0367 +,0xA203 +,0x0363 +,0x08C3 +,0xA206 +,0x0355 +,0x6E00 +,0xBC45 +,0xBCC9 +,0x8000 +,0x698C +,0x2146 +,0x24B5 +,0xA205 +,0x0364 +,0x28E5 +,0x2444 +,0xA303 +,0x0366 +,0x7000 +,0x244E +,0x7008 +,0xE54F +,0x1918 +,0x2640 +,0x8F4A +,0xE14F +,0xA20E +,0x0367 +,0xE540 +,0xA300 +,0x0367 +,0xBC22 +,0x3101 +,0xE0C1 +,0x2409 +,0xFA52 +,0x88C8 +,0x218A +,0x240C +,0x3840 +,0x8F0B +,0xBC20 +,0x2004 +,0x8E00 +,0xFA10 +,0x2680 +,0x3802 +,0x8F04 +,0xBC20 +,0x3100 +,0x5FE4 +,0xFA10 +,0x2108 +,0x181C +,0xA201 +,0x0369 +,0xA204 +,0x0365 +,0x3449 +,0x084C +,0xBC24 +,0x30FE +,0x2610 +,0xA301 +,0x0369 +,0xA201 +,0x0362 +,0xFA94 +,0x195A +,0x0048 +,0x3340 +,0x8F12 +,0x2650 +,0x8F14 +,0xBC20 +,0x3103 +,0xA204 +,0x0361 +,0x69B0 +,0x3A10 +,0x8F02 +,0x2188 +,0x8C04 +,0x185A +,0x0410 +,0x2088 +,0x1853 +,0xA301 +,0x0361 +,0x3822 +,0x8D05 +,0xBC20 +,0x30FE +,0xB028 +,0xFFFF +,0xFB12 +,0x8EC0 +,0xA301 +,0x0362 +,0x8E00 +,0x8EB8 +,0xBC20 +,0x303D +,0x4021 +,0xFA10 +,0xA202 +,0x0462 +,0x1408 +,0x3491 +,0xB000 +,0xFFFF +,0x0810 +,0x2680 +,0xA300 +,0x0462 +,0xA200 +,0x0460 +,0x8F36 +,0xBC23 +,0x3041 +,0xBC22 +,0x3040 +,0x6980 +,0x3A73 +,0xA204 +,0x045B +,0xA21C +,0x045A +,0xFA52 +,0x8F06 +,0x21A3 +,0x8F02 +,0x387C +,0x201A +,0x8F07 +,0x4000 +,0x8D06 +,0x21A3 +,0x8F03 +,0x387C +,0x219A +,0x8F00 +,0x3801 +,0xBC22 +,0x3043 +,0x8E00 +,0xFA52 +,0x2620 +,0x8F17 +,0xA202 +,0x0465 +,0x26A0 +,0x8F12 +,0xBC22 +,0x2004 +,0x8E00 +,0xFA52 +,0x26A0 +,0x8F0C +,0xBC22 +,0x303F +,0xA203 +,0x045E +,0xFA52 +,0x209A +,0x8F05 +,0xBC22 +,0x303E +,0xA203 +,0x045D +,0xFA52 +,0x211A +,0x8F00 +,0x4000 +,0xBC22 +,0x3044 +,0xA300 +,0x0460 +,0xFA50 +,0xA202 +,0x0463 +,0x2680 +,0x8F03 +,0x4000 +,0x8C42 +,0xA300 +,0x0461 +,0xBC20 +,0x2015 +,0xBC23 +,0x3048 +,0xFA10 +,0xFA73 +,0x2003 +,0x4000 +,0x3860 +,0x8F1A +,0xBC20 +,0x2080 +,0xBC24 +,0x3046 +,0xFA10 +,0xFA94 +,0x2184 +,0x3803 +,0x8F07 +,0xBC20 +,0x3047 +,0xBC24 +,0x2015 +,0xFA10 +,0xFA94 +,0x2020 +,0x3803 +,0x8F08 +,0xBC20 +,0x2083 +,0xBC24 +,0x3045 +,0xFA10 +,0xFA94 +,0x2004 +,0x3803 +,0x8F00 +,0x3801 +,0x2680 +,0x8F02 +,0xBC20 +,0x304A +,0x8C05 +,0xFA10 +,0xBC20 +,0x3049 +,0x8E00 +,0xFA10 +,0xBC24 +,0x304B +,0x0E10 +,0xFA92 +,0x2102 +,0x8F04 +,0xBC22 +,0x304C +,0x8E00 +,0xFA52 +,0x2002 +,0x1890 +,0x33A0 +,0x180B +,0xA300 +,0x0461 +,0xBC20 +,0x3042 +,0xA201 +,0x0461 +,0xA203 +,0x0460 +,0xB512 +,0x0001 +,0xFA10 +,0xA302 +,0x0463 +,0x0059 +,0x2600 +,0x8F0A +,0x2601 +,0x8F07 +,0x2602 +,0x4042 +,0x8F02 +,0x2603 +,0x8C04 +,0x1851 +,0x8C02 +,0x4001 +,0x4021 +,0xBC20 +,0x200D +,0x8EC0 +,0x8E00 +,0xFB11 +,0xBC20 +,0x0375 +,0xBC21 +,0x0372 +,0xBC22 +,0x036A +,0xBC3C +,0x0376 +,0x700E +,0xA0C1 +,0x70CF +,0xA040 +,0xBC23 +,0x038F +,0xBC09 +,0x1482 +,0x2442 +,0xE104 +,0xBC26 +,0x1180 +,0x6A39 +,0xA185 +,0xBC21 +,0xF2C0 +,0x6A3A +,0x61C7 +,0x6A3F +,0xA5A5 +,0xE584 +,0xE184 +,0xE185 +,0xBC21 +,0x1CF0 +,0x6A3A +,0x61C7 +,0xBC21 +,0x8620 +,0x6A3E +,0x65A5 +,0x88C0 +,0x2442 +,0x6A39 +,0xA584 +,0xBC21 +,0x0840 +,0x6A3A +,0x6184 +,0x6A3F +,0xA185 +,0xBC21 +,0x0A40 +,0x6A3A +,0x61C7 +,0xBC21 +,0x8620 +,0x6A3E +,0x65A5 +,0x88C0 +,0x8E00 +,0xE584 +,0xE464 +,0xBC23 +,0x038F +,0xBC21 +,0x0375 +,0x8E00 +,0xE4C0 +,0x8EB8 +,0x0000 +,0xA202 +,0x0372 +,0xA203 +,0x0395 +,0x009A +,0xB214 +,0x0014 +,0x8F16 +,0xB024 +,0xFFEC +,0x5FC3 +,0x04DA +,0x3B43 +,0xA200 +,0x0375 +,0xBC3C +,0x0376 +,0x433E +,0xBC23 +,0x305B +,0x77F6 +,0xAA18 +,0x6910 +,0xBA64 +,0xE065 +,0x8A05 +,0xBBB0 +,0xC81D +,0x4023 +,0x8880 +,0xA303 +,0x0373 +,0x8EC0 +,0xA302 +,0x0395 +,0x8E00 +,0xBC20 +,0x03BA +,0xA203 +,0x03B9 +,0x6D20 +,0xA00E +,0xB206 +,0x0080 +,0xE04F +,0xE14C +,0x8F36 +,0x88B0 +,0x40A4 +,0xB226 +,0x01B0 +,0x40C5 +,0x1925 +,0x401C +,0xB226 +,0x06C0 +,0x7007 +,0xA45C +,0x4083 +,0x6607 +,0x255E +,0xA205 +,0x0396 +,0xA202 +,0x03BE +,0xA31C +,0x03B9 +,0xA31C +,0x03BA +,0x2268 +,0x8F03 +,0x8E00 +,0x8C03 +,0xB034 +,0xFFFF +,0x34D1 +,0xA300 +,0x0396 +,0xA202 +,0x03BD +,0xB236 +,0x000A +,0x8F05 +,0xB226 +,0xFFF6 +,0x3B83 +,0x8F04 +,0x4002 +,0x401C +,0x8D02 +,0x4022 +,0x401C +,0x26A1 +,0x8F00 +,0x40A0 +,0xA31C +,0x03BE +,0xA302 +,0x03BD +,0x8C0D +,0xA300 +,0x0397 +,0x2421 +,0xBC25 +,0x1000 +,0x28E5 +,0x34D9 +,0xA303 +,0x03B9 +,0xA30E +,0x03BA +,0xE44F +,0xE54C +,0xA200 +,0x0397 +,0x3048 +,0xBC20 +,0x7E7E +,0x8EC0 +,0xBC82 +,0x0000 +,0x8E00 +,0xBC22 +,0x2131 +,0xBC24 +,0x00B2 +,0x77F6 +,0xBB54 +,0xBC23 +,0x2135 +,0xBC22 +,0x2136 +,0x7087 +,0xBA73 +,0x6910 +,0xFA52 +,0xBCB2 +,0xC000 +,0xBCA2 +,0x8000 +,0xA200 +,0x03A6 +,0x3F1A +,0xBC22 +,0x3060 +,0xBC3C +,0x03A8 +,0x6910 +,0xBF10 +,0xE902 +,0xFA43 +,0x6960 +,0x3E18 +,0x8A06 +,0xBF8C +,0x8618 +,0xBF8C +,0xA410 +,0x2A42 +,0xBC23 +,0x03C4 +,0x88D0 +,0x6D26 +,0xA19E +,0xBC27 +,0x03C7 +,0x6E62 +,0xE15A +,0x6E7A +,0x5FC2 +,0x6E72 +,0x21DC +,0x88A0 +,0x6D4E +,0xA38E +,0xA206 +,0x03A5 +,0xA300 +,0x03A6 +,0x6998 +,0x23CF +,0xE24C +,0xDFE5 +,0x8F03 +,0x8E00 +,0x8C16 +,0xB06C +,0xFFFF +,0x88E0 +,0x39FC +,0x39DE +,0x399A +,0x8880 +,0xBC21 +,0x2045 +,0x2442 +,0x7007 +,0xBB30 +,0xBC20 +,0x2046 +,0xBC21 +,0x305A +,0x7009 +,0xBB16 +,0x7007 +,0x3A30 +,0x3B4C +,0x15B0 +,0x240A +,0x4020 +,0x28C8 +,0xBC21 +,0x03BF +,0xE7CF +,0xA30E +,0x03C7 +,0xBCAA +,0x8000 +,0xA306 +,0x03A5 +,0x690B +,0x60C6 +,0x6E20 +,0x664C +,0x6E7F +,0x2482 +,0x6E77 +,0xA0C7 +,0x6E66 +,0xA4C6 +,0x6A3A +,0x0FC1 +,0xBC20 +,0x3068 +,0x6915 +,0x24CC +,0xA30E +,0x03C4 +,0x6915 +,0xE5CF +,0x6915 +,0xBA01 +,0x6A34 +,0x7A02 +,0x6A3C +,0xBA02 +,0xBC40 +,0x1205 +,0x6A3E +,0xBA02 +,0x6A3A +,0xBA16 +,0xBC40 +,0x1A03 +,0x6A3A +,0x8FE0 +,0x28DE +,0x88A0 +,0xBC40 +,0x1E05 +,0xBC40 +,0x1602 +,0xBC23 +,0x28BE +,0xA204 +,0x03C3 +,0xBCA4 +,0xC000 +,0xB038 +,0x4000 +,0x009A +,0xA302 +,0x03C3 +,0xBC23 +,0x3244 +,0xBCA4 +,0xC000 +,0xBC23 +,0x2111 +,0x8EC0 +,0xE9FE +,0xFB72 +,0xA200 +,0x0398 +,0x2457 +,0xBC22 +,0x306D +,0x77FE +,0xA441 +,0xBC3C +,0x0399 +,0x7067 +,0xBA43 +,0x6E73 +,0xE800 +,0x6915 +,0x3C1C +,0x8A0A +,0xBB8C +,0x861C +,0xBB8C +,0xA413 +,0x28DA +,0xA300 +,0x0398 +,0x8EC0 +,0x8880 +,0x8E00 +,0xE902 +,0xA203 +,0x0372 +,0x6CAC +,0x1FD5 +,0x8F06 +,0xBC20 +,0x036A +,0xBC21 +,0x213E +,0xBC0B +,0x15CB +,0xFA32 +,0xE402 +,0xBC02 +,0x1445 +,0xBC02 +,0x148A +,0xA201 +,0x0372 +,0x41E3 +,0xA202 +,0x0373 +,0x0459 +,0x2621 +,0xA301 +,0x0372 +,0x8F07 +,0x26A2 +,0x8F1A +,0xA200 +,0x0374 +,0xBC02 +,0x1AEC +,0x4002 +,0x8D16 +,0x3820 +,0xBC02 +,0x14AE +,0x3820 +,0xBC02 +,0x1504 +,0xA201 +,0x03B8 +,0x2610 +,0x8F04 +,0xB002 +,0xFFFF +,0x4002 +,0x8C08 +,0xA300 +,0x03B8 +,0x3820 +,0xBC02 +,0x15A4 +,0xA300 +,0x0374 +,0x4042 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0373 +,0x3E02 +,0xBC20 +,0x03E5 +,0x3820 +,0xE002 +,0xE003 +,0xE044 +,0xE402 +,0xE484 +,0xE042 +,0xE482 +,0x7008 +,0xA443 +,0xA200 +,0x03E4 +,0x0C10 +,0xA300 +,0x03E4 +,0x3E01 +,0x8EB8 +,0xBC20 +,0x30BF +,0xA201 +,0x0447 +,0xFA10 +,0x6852 +,0x2902 +,0xBC22 +,0x30BB +,0xBC23 +,0x30BD +,0x18D3 +,0xA202 +,0x0449 +,0xFA64 +,0x3491 +,0x6835 +,0x3A73 +,0x8F65 +,0xA202 +,0x0448 +,0x2153 +,0x8F07 +,0x3449 +,0x3401 +,0xA080 +,0x4000 +,0x4002 +,0x8C5B +,0xA300 +,0x0447 +,0xBC20 +,0x30C1 +,0xA201 +,0x03CF +,0xBC22 +,0x30BA +,0x6114 +,0x5FF5 +,0x701F +,0x3A10 +,0x4023 +,0x6220 +,0xDFDC +,0xB412 +,0x0001 +,0x2620 +,0x8F04 +,0x7000 +,0x5FC1 +,0xA301 +,0x03CB +,0xA301 +,0x03CC +,0xBC22 +,0x30C0 +,0xA201 +,0x03D6 +,0x3449 +,0xFA52 +,0x20CA +,0xA301 +,0x03D6 +,0x8F19 +,0x4041 +,0x0801 +,0x2600 +,0x8F13 +,0x3E02 +,0x4000 +,0xA300 +,0x0099 +,0x3E01 +,0xBC20 +,0x2008 +,0xBC21 +,0xFF7F +,0xFA12 +,0x0851 +,0x7008 +,0x3B11 +,0xBC02 +,0x05B3 +,0x7010 +,0x4FC0 +,0x8C05 +,0xA301 +,0x009A +,0x8C02 +,0x4060 +,0xCFC0 +,0x3302 +,0x8F18 +,0x3541 +,0xBC21 +,0x1111 +,0x2829 +,0x3200 +,0x380E +,0x8F0D +,0x70F0 +,0x4FF5 +,0xBC22 +,0x2042 +,0xBC23 +,0x2041 +,0xBC24 +,0xEEEF +,0xBC0D +,0x1681 +,0xFB51 +,0x6008 +,0x3B70 +,0x8C06 +,0x4002 +,0x8C04 +,0x7000 +,0x8FF5 +,0x7000 +,0x8FF5 +,0xA302 +,0x0448 +,0x8EC0 +,0xE9FE +,0xA302 +,0x0449 +,0xA200 +,0x03CE +,0xB300 +,0x6600 +,0x4020 +,0x3820 +,0x8F00 +,0xA200 +,0x044A +,0x2681 +,0xA300 +,0x044A +,0x8F27 +,0xA200 +,0x03D2 +,0x2600 +,0xBC22 +,0x2044 +,0x4000 +,0x1801 +,0xFA53 +,0x0118 +,0xBC23 +,0x2043 +,0xFB54 +,0xFA72 +,0x0448 +,0x0091 +,0xA204 +,0x03D5 +,0xFB72 +,0xB5C8 +,0x0001 +,0x0061 +,0xA202 +,0x044C +,0x004A +,0xBC23 +,0x2042 +,0xA204 +,0x0448 +,0xA300 +,0x03D2 +,0xBC22 +,0x2041 +,0xA205 +,0x03CA +,0x0020 +,0xFB71 +,0xA300 +,0x0448 +,0xFB55 +,0xBC00 +,0x1612 +,0x8EB8 +,0xA201 +,0x03D5 +,0x3312 +,0xA201 +,0x03CE +,0x8F0A +,0xB312 +,0x3F00 +,0x8F07 +,0xA202 +,0x03D4 +,0x224A +,0x8F04 +,0x4001 +,0x7008 +,0x2441 +,0xA300 +,0x03D0 +,0x8EB8 +,0x2680 +,0xA200 +,0x03CF +,0x8F0A +,0xFA11 +,0xB312 +,0x0198 +,0x8F05 +,0xA201 +,0x03D3 +,0x1641 +,0x40A2 +,0x2E4A +,0x8F00 +,0x3401 +,0x3402 +,0xBC21 +,0x30BB +,0x2041 +,0x8F04 +,0x4000 +,0xA300 +,0x03D0 +,0xBC20 +,0x30B3 +,0xA201 +,0x03D0 +,0x2611 +,0x4001 +,0x8F00 +,0xFA11 +,0xA300 +,0x03CF +,0x8EC0 +,0xB592 +,0x0006 +,0xA301 +,0x03CE +,0x6EF5 +,0x6080 +,0xE906 +,0x7007 +,0x20C1 +,0xA204 +,0x03CE +,0x6313 +,0x1F83 +,0x65B0 +,0x5FA2 +,0x65C0 +,0x1FE3 +,0x7000 +,0x9FC0 +,0x4020 +,0x4207 +,0x5FE6 +,0xBC23 +,0xC6C0 +,0xBC21 +,0x6E40 +,0x38A2 +,0xBC0F +,0x1720 +,0x2F68 +,0x2F20 +,0x8F00 +,0x0D6B +,0x2FB0 +,0x8F00 +,0x0D69 +,0x1785 +,0x3491 +,0x4044 +,0x6815 +,0x0FE4 +,0x4147 +,0x8FEE +,0x6E1D +,0x0FA2 +,0xB036 +,0xFFFB +,0x69A8 +,0x5FE3 +,0x8F08 +,0xB42A +,0x0006 +,0xBC23 +,0x03FF +,0x0893 +,0xA31C +,0x03D5 +,0xDF62 +,0xA302 +,0x03D2 +,0x7000 +,0x8F83 +,0xBC21 +,0x7F80 +,0x3882 +,0xBD10 +,0x174F +,0x2E90 +,0x2F68 +,0x2FB0 +,0x8F0B +,0x26B1 +,0x8F02 +,0x09E9 +,0x2670 +,0x8F03 +,0xBC26 +,0x6E40 +,0x0D6E +,0x8C03 +,0x1785 +,0x3521 +,0x3491 +,0x8E00 +,0xCFA0 +,0x2601 +,0xBC20 +,0x03FF +,0x8F27 +,0xB41A +,0x0006 +,0x0808 +,0x2680 +,0x8F01 +,0x32C2 +,0x8F00 +,0x403C +,0x26B0 +,0xDF7C +,0x8F12 +,0xBC22 +,0x30B3 +,0x6E20 +,0x8FC3 +,0xBC21 +,0x30BB +,0xBD04 +,0x1772 +,0xFA86 +,0x6881 +,0xBA86 +,0x8F01 +,0x2246 +,0x8F03 +,0x21E1 +,0x1914 +,0xA304 +,0x03CF +,0x8E00 +,0x8D0B +,0xCFC0 +,0x6330 +,0x8FE0 +,0xA305 +,0x03D4 +,0xA304 +,0x03D5 +,0xBC02 +,0x16C7 +,0x8D01 +,0xCFC3 +,0x6EAF +,0x8F60 +,0xA303 +,0x03D3 +,0x8EC0 +,0xE9FA +,0xA305 +,0x03D4 +,0xB022 +,0x3098 +,0xA200 +,0x03D2 +,0x6980 +,0x3A45 +,0x8F26 +,0x4343 +,0x0519 +,0x4003 +,0xBC0C +,0x1799 +,0xFA46 +,0x0DAE +,0x2246 +,0x8F01 +,0x3882 +,0x3803 +,0x8E00 +,0x2680 +,0x8F18 +,0x2610 +,0x4046 +,0x4022 +,0x1996 +,0x4205 +,0x3290 +,0x0569 +,0xA306 +,0x03D5 +,0x8F02 +,0x3250 +,0x8F00 +,0x14D5 +,0xBC21 +,0x30A9 +,0x044C +,0x3210 +,0x8F01 +,0x1451 +,0x00D9 +,0xA201 +,0x03D3 +,0x0C4B +,0xA301 +,0x03D3 +,0x8EC0 +,0xA300 +,0x03D2 +,0x8E00 +,0xE904 +,0xA201 +,0x03CC +,0xA200 +,0x03CD +,0x7000 +,0x9F81 +,0xB000 +,0xFFFF +,0xA302 +,0x03CE +,0x6984 +,0x1FB5 +,0x8F4C +,0x2680 +,0x8F47 +,0xA201 +,0x03CF +,0x344A +,0xBC20 +,0x30BB +,0x21C8 +,0xBC20 +,0x30B3 +,0x1841 +,0x6E18 +,0x9FC1 +,0xBC21 +,0x03D7 +,0xBC02 +,0x1700 +,0xA201 +,0x03CF +,0x7000 +,0x8FC0 +,0xA204 +,0x0444 +,0x6882 +,0x1FC1 +,0x4023 +,0x8F06 +,0xB018 +,0xFFFF +,0x6CC7 +,0x9FC0 +,0x6626 +,0x9FE1 +,0x8C20 +,0xDF82 +,0x3422 +,0x6CE1 +,0x1FE0 +,0x181A +,0x2681 +,0xA300 +,0x03CB +,0x8F15 +,0xBC20 +,0x0444 +,0x8A09 +,0xE402 +,0xFA31 +,0xA21E +,0x03D3 +,0xB592 +,0x0006 +,0xA302 +,0x03D0 +,0xA303 +,0x03D1 +,0xA302 +,0x03D5 +,0xA302 +,0x03D2 +,0xA301 +,0x03CE +,0xA31E +,0x03CA +,0xBC02 +,0x1690 +,0xCFE2 +,0xCFC1 +,0xA302 +,0x0444 +,0xA301 +,0x03CF +,0x8C26 +,0x71A0 +,0x0F85 +,0x8C23 +,0xCF85 +,0x2600 +,0x4681 +,0x1848 +,0x7008 +,0x1FC1 +,0x2C48 +,0x401E +,0xBC21 +,0x03D9 +,0xBC20 +,0x03D7 +,0xA31E +,0x03CF +,0x1848 +,0x3862 +,0xBC02 +,0x1700 +,0xA202 +,0x03CF +,0x6988 +,0x0FC0 +,0x4025 +,0x8F09 +,0x0885 +,0x2620 +,0x4006 +,0x8F00 +,0xBC02 +,0x15FE +,0xA306 +,0x0444 +,0x8C02 +,0x4680 +,0xCF85 +,0xCFB5 +,0xA305 +,0x03CC +,0x8EC0 +,0xE9FC +,0xA300 +,0x03CD +,0xE902 +,0xA203 +,0x03CD +,0xB036 +,0xFFFF +,0x698C +,0x1FC3 +,0xDFF5 +,0xBC01 +,0x190F +,0xA201 +,0x03D1 +,0x2690 +,0xBC01 +,0x1920 +,0xB016 +,0xFFE6 +,0x4340 +,0x2048 +,0xBC01 +,0x190A +,0xB306 +,0x0019 +,0xBC01 +,0x18F4 +,0xA201 +,0x03D2 +,0xB306 +,0x0018 +,0x8F7E +,0xB306 +,0x0017 +,0x8F4E +,0xCFC3 +,0xB316 +,0x0016 +,0xBC01 +,0x1920 +,0xA203 +,0x044B +,0x26B0 +,0xBC01 +,0x1920 +,0x4023 +,0x2610 +,0xA303 +,0x044B +,0x4002 +,0x8F0F +,0xBC21 +,0x03D7 +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F07 +,0xA203 +,0x0444 +,0xA21E +,0x03D3 +,0x34D9 +,0xA31E +,0x03CA +,0xA303 +,0x0444 +,0xA203 +,0x0444 +,0xB236 +,0x0080 +,0x8F19 +,0xA203 +,0x0446 +,0xB236 +,0x0080 +,0x7000 +,0xCFC5 +,0xBC21 +,0x0444 +,0x8F09 +,0xA200 +,0x0445 +,0xB200 +,0x0080 +,0x8F12 +,0x8A03 +,0xE483 +,0x3569 +,0xBC02 +,0x15FE +,0x8D0D +,0x8A03 +,0xE483 +,0xB05A +,0xFFFF +,0xBC02 +,0x15FE +,0x8D06 +,0x7000 +,0xCFC5 +,0xBC21 +,0x0444 +,0x8A03 +,0xE483 +,0xA200 +,0x03D2 +,0xDFC5 +,0xBC02 +,0x16DA +,0xBC02 +,0x1690 +,0x8D73 +,0x2610 +,0xBC21 +,0x03D7 +,0x8F24 +,0xBC40 +,0x1880 +,0x4023 +,0x2E03 +,0xBC40 +,0x1C80 +,0x4002 +,0x185A +,0xA200 +,0x03D9 +,0x2E03 +,0x0001 +,0xA300 +,0x03D9 +,0xBC21 +,0x03D9 +,0x441A +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F0B +,0xA203 +,0x0445 +,0xA201 +,0x03D3 +,0x34D9 +,0xA301 +,0x03CA +,0xA31A +,0x044C +,0xA303 +,0x0445 +,0x8C04 +,0x4003 +,0x8C02 +,0x4003 +,0x4003 +,0x8C47 +,0xA303 +,0x044B +,0x2610 +,0xBC21 +,0x03D9 +,0x4002 +,0x4023 +,0x8F3D +,0xBC02 +,0x1700 +,0x2680 +,0xA300 +,0x03D2 +,0x8F37 +,0xA203 +,0x0446 +,0x441E +,0xA201 +,0x03D3 +,0x34D9 +,0xA301 +,0x03CA +,0xA31E +,0x044C +,0xA303 +,0x0446 +,0x8D2C +,0xA203 +,0x03D4 +,0x2630 +,0xBC20 +,0x03D2 +,0x8F00 +,0xBC02 +,0x16C7 +,0xA203 +,0x03D2 +,0x26B0 +,0x8F1E +,0xA203 +,0x0444 +,0xA21E +,0x03D3 +,0x34D9 +,0xA31E +,0x03CA +,0xA303 +,0x0444 +,0x8D16 +,0x4661 +,0x044B +,0xBC02 +,0x1787 +,0x8D11 +,0xA200 +,0x03D7 +,0x4010 +,0x4023 +,0xA300 +,0x03CA +,0xA310 +,0x03D1 +,0xBC21 +,0x03D7 +,0x3843 +,0xBC02 +,0x1700 +,0x4683 +,0xA310 +,0x044C +,0xDFC3 +,0xCFF5 +,0xCFC3 +,0x8EC0 +,0xE9FE +,0xA303 +,0x03CD +,0xE902 +,0x8E00 +,0xDFD5 +,0x3E02 +,0xA200 +,0x03E3 +,0x7000 +,0x5FE0 +,0xA301 +,0x03E3 +,0x2600 +,0x8F12 +,0xA200 +,0x03CB +,0x2680 +,0x8F02 +,0xA200 +,0x03CC +,0x2600 +,0x8F02 +,0xA200 +,0x03CD +,0x2681 +,0x8F06 +,0xBC20 +,0x03E5 +,0xBC21 +,0x03D7 +,0xBD04 +,0x1945 +,0xE002 +,0xE482 +,0x3E01 +,0x8C0E +,0xCFE0 +,0xA200 +,0x03CB +,0x2601 +,0x8F02 +,0xBC02 +,0x17B9 +,0x8C04 +,0xCFE0 +,0xBC02 +,0x183D +,0xCFE0 +,0xB000 +,0xFFFF +,0x69A0 +,0x1FE0 +,0x8FEF +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xBC20 +,0x2048 +,0x8E00 +,0xFA10 +,0x2600 +,0x8F06 +,0xBC20 +,0x2043 +,0xBC22 +,0x2044 +,0x4001 +,0x8EC0 +,0xFB11 +,0xFB51 +,0x8EB8 +,0xA201 +,0x03E1 +,0xBC22 +,0x3079 +,0xFA20 +,0xB030 +,0xFFD8 +,0xB302 +,0x308C +,0xA303 +,0x03EE +,0x8EC0 +,0x1851 +,0xA301 +,0x03E1 +,0xA203 +,0x03E3 +,0x34D9 +,0xA200 +,0x03FD +,0x5FFA +,0xBC3C +,0x03FA +,0x407E +,0xA303 +,0x03E3 +,0x7009 +,0x2461 +,0x6CE4 +,0x3C1E +,0x4003 +,0xA205 +,0x03E4 +,0x19E3 +,0x0C95 +,0x2131 +,0x6555 +,0x2042 +,0x1863 +,0xA300 +,0x03FD +,0x33A0 +,0xB05A +,0x03E6 +,0x1823 +,0x637E +,0x22C0 +,0x2E04 +,0xB5FE +,0x0005 +,0x01C7 +,0x6678 +,0xE6A7 +,0x684C +,0xA2C2 +,0x18E3 +,0x0C0B +,0x2E94 +,0x8EC0 +,0x0097 +,0xE6C2 +,0xA200 +,0x03DB +,0xBC3C +,0x03DC +,0x409E +,0x405A +,0xBC22 +,0x03EA +,0x77FE +,0xAA18 +,0xE05F +,0xBC23 +,0x308C +,0xE51F +,0xBD03 +,0x19C3 +,0x6910 +,0xBC1C +,0xFA65 +,0x8A03 +,0xBBB0 +,0xCA1C +,0x28EC +,0x88C0 +,0x8E00 +,0xE504 +,0x8EC0 +,0xEA18 +,0xA300 +,0x03DB +,0xBC26 +,0x03E2 +,0xA202 +,0x03E9 +,0xE343 +,0x698C +,0x2902 +,0xA203 +,0x03E0 +,0xBC01 +,0x1A6F +,0xA204 +,0x03F6 +,0x69B0 +,0x5FD5 +,0x3883 +,0x8F02 +,0x4004 +,0xA304 +,0x03F6 +,0x3342 +,0x8F68 +,0xBC26 +,0x03F7 +,0x602D +,0x215F +,0x26C0 +,0xE55F +,0x8F61 +,0x6E11 +,0xBCC5 +,0x6CF4 +,0x2341 +,0x4004 +,0x4026 +,0x19B4 +,0x3210 +,0x8F00 +,0x35B1 +,0xBC40 +,0x1102 +,0x3220 +,0x8F00 +,0x35B1 +,0x2663 +,0xA207 +,0x03F1 +,0x8F01 +,0x26E0 +,0x8F09 +,0x2435 +,0x2429 +,0x2412 +,0x20B5 +,0x8F00 +,0x35F9 +,0x2095 +,0x8F00 +,0xB07E +,0xFFFF +,0xA202 +,0x03F2 +,0x3551 +,0xB20A +,0x004C +,0x3844 +,0x8F0B +,0xB23E +,0x0008 +,0x38A7 +,0x4024 +,0x38E2 +,0x8F05 +,0x38E5 +,0x3378 +,0x3882 +,0x8F01 +,0x5FE4 +,0x38E2 +,0x38A2 +,0x00E3 +,0xA305 +,0x03F2 +,0xA307 +,0x03F1 +,0xDFE3 +,0xBC02 +,0x197C +,0xA203 +,0x03F5 +,0xA202 +,0x03F3 +,0x6056 +,0x0FE4 +,0x3491 +,0xB438 +,0x0001 +,0xA305 +,0x03F5 +,0xB204 +,0x0208 +,0x8F14 +,0xA202 +,0x03F5 +,0xA205 +,0x03F4 +,0xB524 +,0x0001 +,0x20AA +,0x401D +,0x8F06 +,0xA202 +,0x03E4 +,0x4024 +,0x0C94 +,0x3883 +,0xA302 +,0x03E4 +,0x4643 +,0xA31D +,0x03F5 +,0xA31D +,0x03F4 +,0x4002 +,0xA303 +,0x03EF +,0xA302 +,0x03F3 +,0xA202 +,0x03EF +,0x2222 +,0x8F09 +,0x3491 +,0x2262 +,0x8F11 +,0xA202 +,0x03E9 +,0x8E00 +,0xE142 +,0xA302 +,0x03F0 +,0x8D0C +,0xA201 +,0x03F0 +,0x7008 +,0x9FE4 +,0xBC02 +,0x197C +,0xA202 +,0x03F4 +,0x6024 +,0x0FE4 +,0xA302 +,0x03F4 +,0xB008 +,0xFFFF +,0x69A0 +,0x0FD5 +,0x8F79 +,0x700F +,0xDFD5 +,0xBC02 +,0x196D +,0xA31F +,0x03F6 +,0xCFD5 +,0x8D73 +,0x7766 +,0xE145 +,0xA202 +,0x03F0 +,0x3822 +,0xBC3D +,0x03F1 +,0x453F +,0xA204 +,0x0442 +,0x69AC +,0x64E5 +,0x6E28 +,0x6A38 +,0x8F02 +,0xA207 +,0x03EE +,0x26F0 +,0x8F15 +,0xE142 +,0xE2C5 +,0x6175 +,0x60C2 +,0x615A +,0xA242 +,0x243F +,0x242D +,0x017D +,0xB05A +,0x0008 +,0xB4DA +,0x0004 +,0x356A +,0xB4DA +,0x0002 +,0x016A +,0x206A +,0x5FE2 +,0x1955 +,0x8C02 +,0xE605 +,0x5FE2 +,0xB006 +,0xFFFF +,0x2680 +,0x8F3F +,0xA203 +,0x0443 +,0x34D9 +,0xA303 +,0x0443 +,0xB236 +,0x00F0 +,0x8F08 +,0xDFC1 +,0xDFF5 +,0xBC24 +,0x041A +,0xBC02 +,0x196D +,0xCFF5 +,0x8C31 +,0xCFC1 +,0xBC24 +,0x041A +,0x4003 +,0x6E38 +,0xE200 +,0x4005 +,0xA071 +,0xC000 +,0xBD27 +,0x1ABA +,0x6659 +,0x6200 +,0xA071 +,0xC000 +,0x1965 +,0xA207 +,0x03EE +,0xB0DA +,0x041A +,0x003D +,0xB450 +,0x0001 +,0xA305 +,0x03EF +,0x26D0 +,0x4685 +,0x4667 +,0x405F +,0x19EF +,0xE71F +,0xA307 +,0x03CD +,0xBC25 +,0x03F0 +,0x8A06 +,0xE703 +,0x8A0A +,0xE683 +,0x8A03 +,0xE682 +,0xBC3F +,0x03FA +,0xA303 +,0x03CC +,0xA31F +,0x03FD +,0xA303 +,0x03CB +,0xA304 +,0x0442 +,0xA301 +,0x03F0 +,0xE9FE +,0xA300 +,0x03E0 +,0xA202 +,0x03E9 +,0x8EC0 +,0x3491 +,0xA302 +,0x03E9 +,0x0000 +,0xE902 +,0xA201 +,0x03DB +,0xDFD5 +,0x6960 +,0x24C0 +,0xBC02 +,0x19AA +,0xBC20 +,0x03EA +,0xA300 +,0x03E9 +,0xBD04 +,0x1AFD +,0xBC02 +,0x19C8 +,0x8E00 +,0x8E00 +,0xCFD5 +,0x8E00 +,0x8EC0 +,0xE9FE +,0x8E00 +,0xE902 +,0xA200 +,0x0466 +,0x6980 +,0x1FC0 +,0xBC01 +,0x1BB4 +,0xB310 +,0x00FF +,0xBC01 +,0x1BBA +,0xA201 +,0x0468 +,0xA202 +,0x0467 +,0xB034 +,0xFFFF +,0x3310 +,0xBC20 +,0x0450 +,0xBC01 +,0x1BAA +,0x3880 +,0x4021 +,0xE20E +,0xE24F +,0xBC24 +,0x3002 +,0x88D8 +,0xFA94 +,0xBCDB +,0x0000 +,0xBC24 +,0x3009 +,0x2435 +,0xFA94 +,0x2134 +,0x4004 +,0x19CC +,0xA307 +,0x0465 +,0xBC27 +,0x3013 +,0xA305 +,0x0464 +,0xFAF7 +,0x21B7 +,0x198C +,0x26E0 +,0x8F04 +,0xBC26 +,0x2004 +,0x8E00 +,0xFAD6 +,0x2660 +,0x8F03 +,0xA206 +,0x046A +,0x35B1 +,0xA306 +,0x046A +,0xBC27 +,0x3011 +,0xA206 +,0x0469 +,0x35B1 +,0xFAF7 +,0x2037 +,0xA306 +,0x0469 +,0x8F0F +,0xBC26 +,0x3012 +,0xA207 +,0x046A +,0xFAD6 +,0x21BE +,0x8F03 +,0x8E00 +,0x8C04 +,0xA304 +,0x046B +,0xA301 +,0x046B +,0xA304 +,0x046A +,0xA304 +,0x0469 +,0xBC26 +,0x300A +,0x8E00 +,0xFAD6 +,0x212E +,0x0526 +,0x19B5 +,0x202C +,0xBC25 +,0x2017 +,0x1926 +,0x6CA8 +,0x3AB2 +,0xBC25 +,0x3006 +,0x8F02 +,0xA303 +,0x0467 +,0xBC25 +,0x3003 +,0xBC23 +,0x300C +,0x8E00 +,0xFA73 +,0x2013 +,0x8F13 +,0xBC26 +,0x300D +,0x34E9 +,0xFAD6 +,0x2016 +,0x8F0C +,0xBC26 +,0x300E +,0x8E00 +,0xFAD6 +,0x2016 +,0x8F05 +,0xBC26 +,0x300F +,0x8E00 +,0xFAD6 +,0x2016 +,0x8C02 +,0x18DD +,0x34EA +,0x38A3 +,0x2442 +,0xFAB2 +,0x28E2 +,0x88A0 +,0xBC23 +,0x300B +,0xB524 +,0x0006 +,0xFA73 +,0xB424 +,0x0006 +,0x32B0 +,0x8F01 +,0x4003 +,0x049A +,0xBC23 +,0x2020 +,0xB524 +,0x0001 +,0xFA73 +,0x0859 +,0x2690 +,0xBC23 +,0x2003 +,0x8F02 +,0x4001 +,0x8C0C +,0xFB71 +,0x3451 +,0x8C09 +,0x7000 +,0x7B71 +,0xB012 +,0xFFFF +,0xA301 +,0x0468 +,0xA303 +,0x0467 +,0x4001 +,0xE401 +,0xE441 +,0x8D06 +,0xBC20 +,0x2003 +,0x5FC1 +,0xFA12 +,0x0851 +,0xFB11 +,0xCFC0 +,0x3401 +,0xE9FE +,0xBC21 +,0x00FF +,0x8EC0 +,0x0801 +,0xA300 +,0x0466 +,0xE904 +,0xBC21 +,0x2016 +,0x6E05 +,0x1FD5 +,0xB000 +,0xFFFD +,0xBC22 +,0x3000 +,0xFA31 +,0x7000 +,0x6441 +,0xFA52 +,0xBC23 +,0x044D +,0xBC24 +,0x044F +,0xBC02 +,0x1E36 +,0xA200 +,0x044F +,0x7003 +,0x0FD5 +,0xBC22 +,0x4444 +,0x6915 +,0xE9FC +,0x2456 +,0x28C2 +,0xBC20 +,0x3001 +,0x8890 +,0xBC22 +,0x0450 +,0x6910 +,0xBA10 +,0x28C8 +,0x6E00 +,0xBC41 +,0x88B4 +,0x7101 +,0x2145 +,0x24A9 +,0x28DC +,0x2444 +,0x8EC0 +,0xE54F +,0xE44E +,0xBC21 +,0x3033 +,0xBC22 +,0x201E +,0xB580 +,0x0001 +,0xFA31 +,0x4043 +,0xFA54 +,0x0923 +,0xB012 +,0xFFFF +,0x2220 +,0x8F01 +,0x3310 +,0x8FF7 +,0x8EB8 +,0xA200 +,0x0470 +,0x3280 +,0xBC21 +,0x0477 +,0xBC22 +,0x0474 +,0x184A +,0xA202 +,0x046D +,0xBC40 +,0x1083 +,0x6CE8 +,0xE084 +,0x66B7 +,0x20C1 +,0x8F04 +,0xB044 +,0x3014 +,0x8E00 +,0xFA94 +,0x211C +,0x8F0B +,0x32A0 +,0xB044 +,0xFFFF +,0x8F07 +,0xB058 +,0x3017 +,0x8E00 +,0xFAB5 +,0x219D +,0x8F02 +,0x3844 +,0x8D01 +,0x3491 +,0xB034 +,0x301A +,0xA302 +,0x046D +,0xFA73 +,0xBC22 +,0x3023 +,0x1A59 +,0x2419 +,0xFA52 +,0x211A +,0x8F05 +,0x3300 +,0x8F02 +,0xBC20 +,0x301F +,0x8C05 +,0xFA10 +,0xBC20 +,0x301E +,0x8E00 +,0xFA10 +,0x4202 +,0x0490 +,0xA203 +,0x0473 +,0x2442 +,0x28DA +,0x28C8 +,0x8884 +,0xBC21 +,0x0200 +,0xBC90 +,0x4000 +,0xBC22 +,0x0800 +,0xBC80 +,0x8000 +,0xBC22 +,0x3024 +,0x2690 +,0x4004 +,0xA203 +,0x0454 +,0x1820 +,0xFA52 +,0x0E4B +,0x210A +,0xA300 +,0x0473 +,0x8F04 +,0xBC20 +,0x3025 +,0x8E00 +,0xFA10 +,0x2008 +,0x1881 +,0x8EC0 +,0xA302 +,0x0454 +,0x8E00 +,0xBC20 +,0x200F +,0xA201 +,0x046E +,0xFA10 +,0x2680 +,0x8F00 +,0x3449 +,0x2682 +,0x4000 +,0x8F00 +,0xB012 +,0xFFFF +,0x3210 +,0x8F02 +,0x3317 +,0x40E0 +,0x1801 +,0x8EC0 +,0xA300 +,0x046E +,0x8E00 +,0xBC20 +,0x3031 +,0xBC21 +,0x2000 +,0xFA12 +,0x0811 +,0x2241 +,0xA200 +,0x046E +,0x8F03 +,0x4E00 +,0x0810 +,0xB400 +,0x0004 +,0xB010 +,0x3026 +,0xA203 +,0x0454 +,0xFA31 +,0xBC24 +,0x1000 +,0x0994 +,0x1AD9 +,0x2274 +,0x34D9 +,0x4025 +,0x111D +,0x8F01 +,0x41E3 +,0x0913 +,0x4002 +,0x3240 +,0x3862 +,0x8F02 +,0x4103 +,0x2123 +,0x18DC +,0xB5C6 +,0x0001 +,0xBC26 +,0x302E +,0x0E4C +,0x6980 +,0x3AD6 +,0xBC24 +,0x200B +,0xB5F0 +,0x0004 +,0xA303 +,0x046F +,0x1895 +,0x0E4E +,0xA300 +,0x046E +,0x00FB +,0x6988 +,0x3B91 +,0x8F01 +,0x2681 +,0x8F00 +,0x4002 +,0x2620 +,0x8F01 +,0x2682 +,0x8F00 +,0x4002 +,0x2620 +,0x8F01 +,0x2683 +,0x8F00 +,0x4002 +,0x2620 +,0x8F40 +,0x2604 +,0x8F3E +,0x2620 +,0x8F01 +,0x2685 +,0x8F00 +,0x4002 +,0x2620 +,0x8F33 +,0x2606 +,0x8F31 +,0x2620 +,0x8F01 +,0x2687 +,0x8F33 +,0xBC20 +,0x2005 +,0xBC21 +,0x0200 +,0xFA10 +,0x0801 +,0x2680 +,0x8F20 +,0xA200 +,0x0452 +,0x2602 +,0x8F11 +,0x2603 +,0x8F03 +,0x4060 +,0x8C25 +,0xA300 +,0x0452 +,0xBC20 +,0x3036 +,0xBC21 +,0x2081 +,0xFA10 +,0xFA31 +,0x2088 +,0x4040 +,0x8F18 +,0xA300 +,0x0452 +,0x8D17 +,0xBC20 +,0x3037 +,0xBC21 +,0x2081 +,0xFA10 +,0xFA31 +,0x2188 +,0x4060 +,0x8F0C +,0xA300 +,0x0452 +,0x8D0B +,0x4060 +,0xA300 +,0x0452 +,0x8D07 +,0x4020 +,0x8C05 +,0xA300 +,0x0452 +,0x4000 +,0xA300 +,0x0452 +,0xA200 +,0x0452 +,0xB000 +,0x3039 +,0xBC21 +,0x2006 +,0xFA10 +,0x8EC0 +,0x0003 +,0xFB30 +,0xA200 +,0x0474 +,0xA201 +,0x0453 +,0xB500 +,0x0007 +,0xBC22 +,0x302F +,0x1AC8 +,0x241B +,0xFA52 +,0x211A +,0x8F02 +,0xBC22 +,0x3021 +,0x8C05 +,0xFA52 +,0xBC22 +,0x3020 +,0x8E00 +,0xFA52 +,0xA204 +,0x046C +,0xBC23 +,0x8000 +,0x04DA +,0x3340 +,0x2457 +,0x2456 +,0x8F04 +,0x2454 +,0x28CB +,0x28C2 +,0x8C03 +,0x8880 +,0xA30E +,0x046C +,0xBC21 +,0x3030 +,0xBC22 +,0x3032 +,0xA300 +,0x0453 +,0xFA31 +,0xFA52 +,0xBC23 +,0x1000 +,0x0913 +,0x1A08 +,0xBC25 +,0x0400 +,0x2263 +,0xBC81 +,0x4000 +,0x8F01 +,0xBC20 +,0x0FFF +,0x0810 +,0xBC21 +,0x200C +,0x8EC0 +,0x8E00 +,0xFB30 +,0x0000 +,0xBC20 +,0x3022 +,0xBC21 +,0x3038 +,0x7017 +,0xBA10 +,0x700C +,0x3A31 +,0xA310 +,0x046C +,0xA31E +,0x0470 +,0xA300 +,0x0454 +,0xA301 +,0x0452 +,0x6EE5 +,0x6800 +,0xBD0F +,0x1D81 +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0301 +,0x7008 +,0x3B30 +,0xBC02 +,0x1BF3 +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0201 +,0x7000 +,0x3B30 +,0xBC02 +,0x1BF3 +,0x8E00 +,0x8E00 +,0xBC20 +,0x3034 +,0xBC21 +,0x2005 +,0xFA10 +,0xB000 +,0x0301 +,0x7008 +,0x3B30 +,0xBC02 +,0x1BF3 +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xA201 +,0x046E +,0xBC20 +,0x3034 +,0xB012 +,0x3026 +,0x6EAF +,0x3A10 +,0xBC22 +,0x3035 +,0xBC23 +,0x2005 +,0xFA31 +,0xB000 +,0x0201 +,0xFA52 +,0xA301 +,0x0454 +,0xFB70 +,0xBC24 +,0x2009 +,0x8EC0 +,0x7008 +,0x3B72 +,0xFB90 +,0xE902 +,0xA200 +,0x0470 +,0x6CC0 +,0x1FD5 +,0x8F34 +,0xA200 +,0x0472 +,0xA201 +,0x0471 +,0x2680 +,0x8F0F +,0xB312 +,0x007F +,0xBC20 +,0x3035 +,0x8F07 +,0xFA10 +,0xB000 +,0x0101 +,0xBC21 +,0x2005 +,0x8C03 +,0x7008 +,0x3B30 +,0x4020 +,0x8C1E +,0xA300 +,0x0472 +,0xB232 +,0x007F +,0x4000 +,0x8F00 +,0x3409 +,0x3300 +,0xA300 +,0x0471 +,0x8F0A +,0xBC02 +,0x1C65 +,0xBC02 +,0x1C7B +,0xBC20 +,0x3035 +,0xBC21 +,0x2005 +,0xFA10 +,0x8C07 +,0x7000 +,0x3B30 +,0xBC02 +,0x1C04 +,0xBC02 +,0x1C7B +,0x4000 +,0xA300 +,0x0472 +,0xBC02 +,0x1D12 +,0x8D13 +,0xBC02 +,0x1C04 +,0xBC02 +,0x1C7B +,0xA200 +,0x0470 +,0xB000 +,0xFFFF +,0xA201 +,0x0471 +,0xA300 +,0x0470 +,0xB232 +,0x007F +,0x4000 +,0x8F00 +,0x3409 +,0xA300 +,0x0471 +,0x7008 +,0x4FD5 +,0xBC20 +,0x2009 +,0x8EC0 +,0xE9FE +,0xFB11 +,0xBC21 +,0x2010 +,0xE908 +,0xBC20 +,0x200E +,0xFA31 +,0xFA12 +,0xBC24 +,0x7F00 +,0x6E1D +,0x1F95 +,0xB036 +,0xFFF9 +,0x0894 +,0xB444 +,0x0008 +,0x6E10 +,0xE581 +,0xFA10 +,0x73F8 +,0x65C4 +,0x0801 +,0xBC21 +,0x0474 +,0xBC40 +,0x1500 +,0xDFA1 +,0xBD03 +,0x1E2E +,0xE0DC +,0xE101 +,0xDFC2 +,0xDFFC +,0xBC02 +,0x1E46 +,0xCFE1 +,0x63A0 +,0x4FA1 +,0x6D34 +,0x4FC2 +,0x6E20 +,0x6480 +,0xB406 +,0x0001 +,0xBC40 +,0x1E00 +,0xDFA1 +,0x7000 +,0x0F95 +,0xBC21 +,0x2009 +,0x8EC0 +,0xE9F8 +,0xFB30 +,0xE040 +,0x6C00 +,0x6246 +,0x6E08 +,0xE185 +,0x6681 +,0xA1C6 +,0x24B5 +,0x28C2 +,0x2444 +,0x8E00 +,0xE5CF +,0x88B8 +,0x8EC0 +,0xE4CE +,0xE643 +,0x3291 +,0x8F0C +,0x24C1 +,0x1448 +,0x41A2 +,0x2442 +,0x4403 +,0x0410 +,0x28CB +,0xB580 +,0x0004 +,0x8890 +,0x8EC0 +,0x0001 +,0x8E00 +,0x8EC0 +,0x4000 +,0x8E00 +,0xBC20 +,0x2092 +,0x4041 +,0xFA10 +,0xBC22 +,0x2093 +,0x0841 +,0x6984 +,0xBA51 +,0x8F0F +,0x4022 +,0x0802 +,0x2681 +,0x8F17 +,0xBC20 +,0x2000 +,0x21C8 +,0xBC20 +,0x2095 +,0x8F02 +,0x8EC0 +,0xE0C1 +,0xFB11 +,0xFA31 +,0xFB11 +,0x8EB8 +,0xBC20 +,0x2094 +,0xBC22 +,0x2000 +,0x6872 +,0xBA10 +,0x8F02 +,0x8EC0 +,0xE4C0 +,0x8E00 +,0x8EC0 +,0xFB30 +,0x8E00 +,0x8EB8 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; +#endif + +const unsigned short bin_patch_E1[] = { +0x2000 +,0x21FF +,0xBC24 +,0x20A0 +,0x8E00 +,0xFA95 +,0xB30A +,0x06AF +,0x8F2E +,0xB30A +,0x08E5 +,0x8F07 +,0xBC25 +,0x08E5 +,0xFB95 +,0xBC22 +,0x399E +,0xBC23 +,0x199E +,0xBC00 +,0x0841 +,0xBC25 +,0x06AF +,0xFB95 +,0x5400 +,0xBC21 +,0xD0B1 +,0xBC02 +,0x07CA +,0x5500 +,0xBC21 +,0x07C2 +,0xBC02 +,0x07CA +,0x40A0 +,0xBC21 +,0x0359 +,0xBC02 +,0x07CA +,0x41A0 +,0xBC21 +,0x00A0 +,0xBC02 +,0x07CA +,0x41C0 +,0xBC21 +,0x4208 +,0xBC02 +,0x07CA +,0x4380 +,0xBC21 +,0x2800 +,0xBC02 +,0x07CA +,0x4E04 +,0xBC00 +,0x08E6 +,0x4344 +,0xBC25 +,0x0400 +,0x2620 +,0x8F06 +,0xBC02 +,0x07F0 +,0x5404 +,0x4025 +,0xBC02 +,0x07FB +,0xBC00 +,0x06C1 +,0xBC02 +,0x07FB +,0x5404 +,0x4025 +,0xBC02 +,0x07F0 +,0xBC00 +,0x06C1 +,0xBDC8 +,0x404E +,0x8E00 +,0xFA11 +,0xBC00 +,0x0630 +,0x8E00 +,0x8E00 +,0x8E00 +,0xBC21 +,0x0002 +,0xBC20 +,0x2008 +,0xBC00 +,0x01BB +,0xBC21 +,0x033F +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7010 +,0x4FF5 +,0xBC22 +,0x201A +,0xBC00 +,0x0161 +,0x4044 +,0xBC25 +,0x1000 +,0xBC02 +,0x07F0 +,0x4E24 +,0xBC00 +,0x0705 +,0xBC22 +,0x399E +,0xBC23 +,0x199E +,0xBC00 +,0x078A +,0xBC24 +,0x2080 +,0x6C88 +,0x3A10 +,0xFA94 +,0xB548 +,0x0005 +,0xBC00 +,0x0E9F +,0xE902 +,0xBC26 +,0x2023 +,0xDFE4 +,0xBC24 +,0x2000 +,0xFAD6 +,0x0934 +,0x26C0 +,0x8F01 +,0xBC26 +,0x3056 +,0x8D02 +,0xBC26 +,0x31F9 +,0xCFE4 +,0xE9FE +,0xBC00 +,0x0FED +,0xBC20 +,0x2090 +,0xBC21 +,0x0100 +,0xFA12 +,0xE902 +,0x0851 +,0x6984 +,0x1FD5 +,0x8F37 +,0x8E00 +,0x8D03 +,0x8E00 +,0xBC20 +,0x2090 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x2600 +,0x8FF5 +,0xBC20 +,0x2090 +,0xBC21 +,0x2091 +,0x714F +,0xBA10 +,0xBC22 +,0x666D +,0x7028 +,0xBB32 +,0x71F8 +,0xBB32 +,0xA203 +,0x0457 +,0x0802 +,0xA204 +,0x0458 +,0x6980 +,0x3B33 +,0xFB34 +,0xBC22 +,0x2545 +,0xA31E +,0x0459 +,0xFB32 +,0x8F0C +,0x2601 +,0x4FE1 +,0x8F0D +,0x2602 +,0xBC21 +,0x0380 +,0x8F09 +,0x2683 +,0x4001 +,0x8F05 +,0xBC02 +,0x40E7 +,0x8D04 +,0xBC21 +,0x03FF +,0xA301 +,0x0456 +,0xA301 +,0x0455 +,0xA200 +,0x0458 +,0xA201 +,0x0457 +,0x260F +,0x8F02 +,0x8E00 +,0x8C03 +,0x3401 +,0x3449 +,0x4000 +,0xCFD5 +,0xA300 +,0x0458 +,0x8EC0 +,0xE9FE +,0xA301 +,0x0457 +,0xBC22 +,0x3105 +,0xA200 +,0x0313 +,0x77DE +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2091 +,0xBC3C +,0x02E0 +,0xBC23 +,0x666D +,0x7000 +,0xFB53 +,0x700E +,0xAA18 +,0xBC24 +,0x0B12 +,0xFB54 +,0x6D36 +,0x7C1C +,0x6C8D +,0x7B54 +,0x8FF9 +,0xA203 +,0x0355 +,0xFB53 +,0xA203 +,0x035A +,0xFB53 +,0xA203 +,0x0464 +,0xBC24 +,0x2004 +,0xFB53 +,0xFA94 +,0xA203 +,0x047F +,0xFB54 +,0xFB53 +,0xA204 +,0x0480 +,0xFB54 +,0xA203 +,0x0481 +,0xFB53 +,0xA204 +,0x0361 +,0xA203 +,0x0362 +,0xFB54 +,0xFB53 +,0xBC23 +,0x5A5A +,0xFB53 +,0x8EC0 +,0xBC23 +,0x2545 +,0xFB53 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_patch_E2[] = { +0x2000 +,0x21FF +,0x8E00 +,0x8E00 +,0x8E00 +,0xBC21 +,0x0002 +,0xBC20 +,0x2008 +,0xBC00 +,0x01A9 +,0xBC21 +,0x033F +,0xA202 +,0x0083 +,0xFB11 +,0x8EA2 +,0xBC20 +,0x2008 +,0x7010 +,0x4FF5 +,0xBC22 +,0x201A +,0xBC00 +,0x014F +,0x240C +,0xA301 +,0x047F +,0xA30F +,0x0480 +,0xA30E +,0x0481 +,0xBC00 +,0x1353 +,0x5380 +,0xBC21 +,0xAC40 +,0xBC02 +,0x07EA +,0x4380 +,0xBC21 +,0x2C00 +,0xBC02 +,0x07EA +,0x43A0 +,0xBC21 +,0xFB40 +,0xBC02 +,0x07EA +,0x43C0 +,0xBC21 +,0x0546 +,0xBC02 +,0x07EA +,0x43E0 +,0xBC21 +,0xFB3C +,0xBC02 +,0x07EA +,0x4400 +,0xBC21 +,0x0537 +,0xBC02 +,0x07EA +,0x4E04 +,0xBC00 +,0x092A +,0x4025 +,0xBC21 +,0x2023 +,0xBC22 +,0x0400 +,0xFA31 +,0x084A +,0x2610 +,0x8F01 +,0xBC02 +,0x081B +,0x8D02 +,0xBC02 +,0x0810 +,0x4E24 +,0xBC00 +,0x0722 +,0x4280 +,0xBC02 +,0x07EA +,0xBC22 +,0x8018 +,0xBC23 +,0x8098 +,0xCFE0 +,0x2600 +,0x1853 +,0x42C0 +,0xBC02 +,0x07EA +,0x4240 +,0xBC21 +,0xE400 +,0xBC02 +,0x07EA +,0x4260 +,0xBC21 +,0x0010 +,0xBC02 +,0x07EA +,0x4040 +,0xBC21 +,0x0FFB +,0xBC02 +,0x07EA +,0x4220 +,0xBC21 +,0x2020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07F8 +,0x4220 +,0xBC21 +,0x1020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0005 +,0x4461 +,0xBC02 +,0x07F8 +,0x4220 +,0xBC21 +,0x4020 +,0xBC02 +,0x07EA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07F8 +,0x4240 +,0xBC21 +,0xE407 +,0xBC02 +,0x07EA +,0x4260 +,0xBC21 +,0x7010 +,0xBC02 +,0x07EA +,0xBC20 +,0x0064 +,0x4461 +,0xBC02 +,0x07F8 +,0x4520 +,0xBC21 +,0x8001 +,0xBC02 +,0x07EA +,0xBC00 +,0x0794 +,0xBC20 +,0x2090 +,0xBC21 +,0x0100 +,0xFA12 +,0xE902 +,0x0851 +,0x6984 +,0x1FD5 +,0x8F37 +,0x8E00 +,0x8D03 +,0x8E00 +,0xBC20 +,0x2090 +,0xBC21 +,0x8000 +,0xFA10 +,0x0801 +,0x2600 +,0x8FF5 +,0xBC20 +,0x2090 +,0xBC21 +,0x2091 +,0x714F +,0xBA10 +,0xBC22 +,0x666D +,0x7028 +,0xBB32 +,0x71F8 +,0xBB32 +,0xA203 +,0x045B +,0x0802 +,0xA204 +,0x045C +,0x6980 +,0x3B33 +,0xFB34 +,0xBC22 +,0x2545 +,0xA31E +,0x045D +,0xFB32 +,0x8F0C +,0x2601 +,0x4FE1 +,0x8F0D +,0x2602 +,0xBC21 +,0x0380 +,0x8F09 +,0x2683 +,0x4001 +,0x8F05 +,0xBC02 +,0x40F6 +,0x8D04 +,0xBC21 +,0x03FF +,0xA301 +,0x045A +,0xA301 +,0x0459 +,0xA200 +,0x045C +,0xA201 +,0x045B +,0x260F +,0x8F02 +,0x8E00 +,0x8C03 +,0x3401 +,0x3449 +,0x4000 +,0xCFD5 +,0xA300 +,0x045C +,0x8EC0 +,0xE9FE +,0xA301 +,0x045B +,0xBC22 +,0x3105 +,0xA200 +,0x0314 +,0x77DE +,0xBA52 +,0x3BC2 +,0xBC22 +,0x2091 +,0xBC3C +,0x02E1 +,0xBC23 +,0x666D +,0x7000 +,0xFB53 +,0x700E +,0xAA18 +,0xBC24 +,0x0B12 +,0xFB54 +,0x6D36 +,0x7C1C +,0x6C8D +,0x7B54 +,0x8FF9 +,0xA203 +,0x0356 +,0xFB53 +,0xA203 +,0x035D +,0xFB53 +,0xA203 +,0x0468 +,0xBC24 +,0x2004 +,0xFB53 +,0xFA94 +,0xA203 +,0x0483 +,0xFB54 +,0xFB53 +,0xA204 +,0x0484 +,0xFB54 +,0xA203 +,0x0485 +,0xFB53 +,0xA204 +,0x0364 +,0xA203 +,0x0365 +,0xFB54 +,0xFB53 +,0xBC23 +,0x5A5A +,0xFB53 +,0x8EC0 +,0xBC23 +,0x2545 +,0xFB53 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_coeff_E1[] = { +0x0000 +,0x01FF +,0x0400 +,0x0006 +,0x2AAB +,0x0324 +,0x0324 +,0x0324 +,0x010C +,0x010C +,0x010C +,0x1111 +,0x1259 +,0x0001 +,0x005A +,0x0E9B +,0x0FFF +,0x0FFF +,0x0008 +,0x0001 +,0x0001 +,0x0CCD +,0xFFE0 +,0xFFD8 +,0x00FF +,0xFFAC +,0xFFBC +,0xFF00 +,0x0020 +,0x0048 +,0x0050 +,0x0050 +,0x000E +,0x0002 +,0x7000 +,0x0800 +,0xFFF8 +,0x0008 +,0x002B +,0xFFF6 +,0xFFF8 +,0xFFFE +,0x0003 +,0x0008 +,0x000D +,0x000F +,0x0014 +,0x0019 +,0x0000 +,0x0800 +,0x6580 +,0x0000 +,0x0000 +,0x7FFF +,0x0008 +,0x0078 +,0xFEF5 +,0xFEE8 +,0x0003 +,0x0080 +,0x0080 +,0x0080 +,0x0300 +,0x0006 +,0xC080 +,0xF000 +,0x0660 +,0xDA80 +,0x0000 +,0x0001 +,0x0001 +,0xFFE4 +,0xFFE8 +,0x0080 +,0x0034 +,0x0001 +,0xFFFF +,0x0001 +,0xFFFE +,0x3AC0 +,0x3340 +,0x2BC0 +,0x07C0 +,0x05C0 +,0x03E0 +,0x0008 +,0x1000 +,0x2000 +,0xFF01 +,0xFFE5 +,0xFFE9 +,0x0DA8 +,0x000E +,0xF75E +,0x1136 +,0xEC7B +,0x0D3C +,0xFA9A +,0xFC47 +,0xF58B +,0x1055 +,0x3DDA +,0x3DDA +,0x1055 +,0xF58B +,0xFC47 +,0x1B17 +,0x362A +,0x1B17 +,0x67DA +,0xA798 +,0xFDA6 +,0xF8BE +,0xF36E +,0xF0D4 +,0xF368 +,0xFB18 +,0x04E8 +,0x0C98 +,0x0F2C +,0x0C92 +,0x0742 +,0x025A +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x712C +,0xF1A8 +,0xF9D4 +,0x208E +,0x4BC2 +,0xF280 +,0xF280 +,0x4BC2 +,0x208E +,0xF9D4 +,0xF1A8 +,0x712C +,0x0000 +,0x0200 +,0x0100 +,0x0080 +,0x0040 +,0x0020 +,0x0010 +,0x0008 +,0x0004 +,0x0002 +,0x0001 +,0x02DC +,0x016E +,0x00B7 +,0x0287 +,0x039F +,0x0313 +,0x0355 +,0x0376 +,0x01BB +,0x0201 +,0x03DC +,0x01EE +,0x00F7 +,0x02A7 +,0x038F +,0x031B +,0x00FC +,0x00FC +,0x0198 +,0x0198 +,0x0168 +,0x0350 +,0x01B4 +,0x01B4 +,0x0089 +,0x002C +,0x0058 +,0x002C +,0x0400 +,0x0000 +,0x0003 +,0xFAED +,0xFED0 +,0x09E2 +,0x166A +,0x1BEF +,0x166A +,0x09E2 +,0xFED0 +,0xFAED +,0x2715 +,0x58EB +,0x58EB +,0x2715 +,0xFF8F +,0xFF25 +,0xFEA1 +,0xFE12 +,0xFD8A +,0xFD26 +,0xFD04 +,0xFD43 +,0xFE00 +,0xFF4E +,0x0139 +,0x03B9 +,0x06BB +,0x0A1A +,0x0DA5 +,0x111F +,0x144B +,0x16EC +,0x18CC +,0x19C7 +,0x19C7 +,0x18CC +,0x16EC +,0x144B +,0x111F +,0x0DA5 +,0x0A1A +,0x06BB +,0x03B9 +,0x0139 +,0xFF4E +,0xFE00 +,0xFD43 +,0xFD04 +,0xFD26 +,0xFD8A +,0xFE12 +,0xFEA1 +,0xFF25 +,0xFF8F +,0x0002 +,0x0004 +,0x47B3 +,0xBAC5 +,0x0B85 +,0x0005 +,0x299A +,0x0004 +,0x000A +,0x0660 +,0x0CCD +,0x0003 +,0x0006 +,0x0080 +,0x002C +,0x0020 +,0x0027 +,0xFF4F +,0xFDB1 +,0xFE2E +,0x0465 +,0x0EF1 +,0x161E +,0x1382 +,0x0983 +,0x007B +,0xFD66 +,0xFE7D +,0xFFE2 +,0x0031 +,0x000D +,0x4000 +,0xFD24 +,0x513A +,0xCAEC +,0x3514 +,0xAEC6 +,0x02DC +,0x4000 +,0xEFB5 +,0x6EAE +,0x8DAB +,0x7255 +,0x9152 +,0x104B +,0x2518 +,0x1FBB +,0x14A2 +,0x0D6A +,0x08B9 +,0x05AC +,0x03B0 +,0x0266 +,0x018F +,0x0104 +,0x00A9 +,0x006E +,0x0047 +,0x0001 +,0x0164 +,0x019A +,0x0001 +,0x0002 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0100 +,0xF500 +,0x1C00 +,0x5A00 +,0x0100 +,0xFF00 +,0xF800 +,0x2000 +,0x4F00 +,0x0100 +,0xFE00 +,0xFC00 +,0x2200 +,0x4700 +,0x0000 +,0xFD00 +,0x0100 +,0x2300 +,0x3D00 +,0xFF00 +,0xFE00 +,0x0500 +,0x2200 +,0x3600 +,0xFF00 +,0xFF00 +,0x0900 +,0x2100 +,0x2F00 +,0x0000 +,0x0100 +,0x0C00 +,0x1F00 +,0x2900 +,0x0000 +,0x0300 +,0x0E00 +,0x1D00 +,0x2500 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0004 +,0x0008 +,0x0308 +,0x0312 +,0x01CC +,0x017C +,0x0019 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xE000 +,0x1840 +,0xC880 +,0xFFEE +,0x0000 +,0x4000 +,0x2680 +,0xFF81 +,0xE000 +,0x5000 +,0xD080 +,0xFFB3 +,0xF800 +,0x4500 +,0xD380 +,0xFFE2 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0F80 +,0xDB80 +,0x21C0 +,0xFFCC +,0x0000 +,0xC680 +,0x0540 +,0x0023 +,0x33C0 +,0xDAC0 +,0x5900 +,0xFFDA +,0x0AC0 +,0xDF80 +,0x1940 +,0xFFF7 +,0x7FFF +,0x50C3 +,0x47FA +,0x4026 +,0x392C +,0x32F5 +,0x2D6A +,0x287A +,0x2413 +,0x2027 +,0x1CA8 +,0x198A +,0x16C3 +,0x1449 +,0x1214 +,0x101D +,0x0E5D +,0x0CCD +,0x0B68 +,0x0A2B +,0x0910 +,0x0813 +,0x0015 +,0x0002 +,0x0080 +,0x2848 +,0x051F +,0x0001 +,0x0010 +,0xFC40 +,0xFC40 +,0xFD94 +,0xFD80 +,0xFE80 +,0xFE80 +,0xFE7C +,0xFE7F +,0x02F4 +,0x0001 +,0x0080 +,0x0080 +,0x1000 +,0x0080 +,0x1000 +,0x1000 +,0x0400 +,0x599A +,0x199A +,0x0666 +,0x0021 +,0x2000 +,0x2000 +,0x2000 +,0xFFE4 +,0x0032 +,0x000A +,0x2000 +,0x4000 +,0x0800 +,0x0400 +,0x000C +,0x0005 +,0x000C +,0x00FF +,0x083D +,0x4000 +,0x062F +,0x404C +,0x01B9 +,0x4052 +,0x0155 +,0x405B +,0x0704 +,0x4069 +,0x0786 +,0x4071 +,0x0E9A +,0x4077 +,0x0FEB +,0x4080 +,0x0000 +,0x0000 +,0xFFD5 +,0x0001 +,0x0375 +,0x001E +,0x0AAB +,0x2000 +,0x2AAB +,0x0040 +,0x0005 +,0x001E +,0x4093 +,0xFEE0 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +}; + +const unsigned short bin_coeff_E2[] = { +0x0000 +,0x01FF +,0x0400 +,0x0006 +,0x2AAB +,0x0324 +,0x0324 +,0x0324 +,0x010C +,0x010C +,0x010C +,0x1111 +,0x1259 +,0x0001 +,0x005A +,0x0E9B +,0x0FFF +,0x0FFF +,0x0020 +,0x0001 +,0x0001 +,0x0CCD +,0xFFE0 +,0xFFD8 +,0x00FF +,0xFFAC +,0xFFBC +,0xFF00 +,0x0020 +,0x0048 +,0x0050 +,0x0050 +,0x000E +,0x0002 +,0x7000 +,0x0800 +,0xFFF8 +,0x0008 +,0x002B +,0xFFF6 +,0xFFF8 +,0xFFFE +,0x0003 +,0x0008 +,0x000D +,0x000F +,0x0014 +,0x0019 +,0x0000 +,0x0800 +,0x6580 +,0x0000 +,0x0000 +,0x7FFF +,0x0008 +,0x0078 +,0xFEF5 +,0xFEE8 +,0x0003 +,0x0080 +,0x0080 +,0x0080 +,0x0300 +,0x0006 +,0xC080 +,0xF000 +,0x0660 +,0xDA80 +,0x0000 +,0x0001 +,0x0001 +,0xFFE4 +,0xFFE8 +,0x0080 +,0x0034 +,0x0001 +,0xFFFF +,0x0001 +,0xFFFE +,0x3AC0 +,0x3340 +,0x2BC0 +,0x07C0 +,0x05C0 +,0x03E0 +,0x0008 +,0x1000 +,0x2000 +,0xFF01 +,0xFFE5 +,0xFFE9 +,0x0DA8 +,0x000E +,0xF75E +,0x1136 +,0xEC7B +,0x0D3C +,0xFA9A +,0xFC47 +,0xF58B +,0x1055 +,0x3DDA +,0x3DDA +,0x1055 +,0xF58B +,0xFC47 +,0x1B17 +,0x362A +,0x1B17 +,0x67DA +,0xA798 +,0xFDA6 +,0xF8BE +,0xF36E +,0xF0D4 +,0xF368 +,0xFB18 +,0x04E8 +,0x0C98 +,0x0F2C +,0x0C92 +,0x0742 +,0x025A +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x0029 +,0x0028 +,0x712C +,0xF1A8 +,0xF9D4 +,0x208E +,0x4BC2 +,0xF280 +,0xF280 +,0x4BC2 +,0x208E +,0xF9D4 +,0xF1A8 +,0x712C +,0x0000 +,0x0200 +,0x0100 +,0x0080 +,0x0040 +,0x0020 +,0x0010 +,0x0008 +,0x0004 +,0x0002 +,0x0001 +,0x02DC +,0x016E +,0x00B7 +,0x0287 +,0x039F +,0x0313 +,0x0355 +,0x0376 +,0x01BB +,0x0201 +,0x03DC +,0x01EE +,0x00F7 +,0x02A7 +,0x038F +,0x031B +,0x00FC +,0x00FC +,0x0198 +,0x0198 +,0x0168 +,0x0350 +,0x01B4 +,0x01B4 +,0x0089 +,0x002C +,0x0058 +,0x002C +,0x0400 +,0x0000 +,0x0003 +,0xFAED +,0xFED0 +,0x09E2 +,0x166A +,0x1BEF +,0x166A +,0x09E2 +,0xFED0 +,0xFAED +,0x2715 +,0x58EB +,0x58EB +,0x2715 +,0xFF8F +,0xFF25 +,0xFEA1 +,0xFE12 +,0xFD8A +,0xFD26 +,0xFD04 +,0xFD43 +,0xFE00 +,0xFF4E +,0x0139 +,0x03B9 +,0x06BB +,0x0A1A +,0x0DA5 +,0x111F +,0x144B +,0x16EC +,0x18CC +,0x19C7 +,0x19C7 +,0x18CC +,0x16EC +,0x144B +,0x111F +,0x0DA5 +,0x0A1A +,0x06BB +,0x03B9 +,0x0139 +,0xFF4E +,0xFE00 +,0xFD43 +,0xFD04 +,0xFD26 +,0xFD8A +,0xFE12 +,0xFEA1 +,0xFF25 +,0xFF8F +,0x0002 +,0x0004 +,0x47B3 +,0xBAC5 +,0x0B85 +,0x0005 +,0x299A +,0x0004 +,0x000A +,0x0660 +,0x0CCD +,0x0003 +,0x0006 +,0x0080 +,0x002C +,0x0020 +,0x0027 +,0xFF4F +,0xFDB1 +,0xFE2E +,0x0465 +,0x0EF1 +,0x161E +,0x1382 +,0x0983 +,0x007B +,0xFD66 +,0xFE7D +,0xFFE2 +,0x0031 +,0x000D +,0x4000 +,0xFD24 +,0x513A +,0xCAEC +,0x3514 +,0xAEC6 +,0x02DC +,0x4000 +,0xEFB5 +,0x6EAE +,0x8DAB +,0x7255 +,0x9152 +,0x104B +,0x2518 +,0x1FBB +,0x14A2 +,0x0D6A +,0x08B9 +,0x05AC +,0x03B0 +,0x0266 +,0x018F +,0x0104 +,0x00A9 +,0x006E +,0x0047 +,0x0001 +,0x0164 +,0x019A +,0x0001 +,0x0002 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0100 +,0xF500 +,0x1C00 +,0x5A00 +,0x0100 +,0xFF00 +,0xF800 +,0x2000 +,0x4F00 +,0x0100 +,0xFE00 +,0xFC00 +,0x2200 +,0x4700 +,0x0000 +,0xFD00 +,0x0100 +,0x2300 +,0x3D00 +,0xFF00 +,0xFE00 +,0x0500 +,0x2200 +,0x3600 +,0xFF00 +,0xFF00 +,0x0900 +,0x2100 +,0x2F00 +,0x0000 +,0x0100 +,0x0C00 +,0x1F00 +,0x2900 +,0x0000 +,0x0300 +,0x0E00 +,0x1D00 +,0x2500 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x7FFF +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0004 +,0x0008 +,0x0308 +,0x0312 +,0x01CC +,0x017C +,0x0019 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xE000 +,0x1840 +,0xC880 +,0xFFEE +,0x0000 +,0x4000 +,0x2680 +,0xFF81 +,0xE000 +,0x5000 +,0xD080 +,0xFFB3 +,0xF800 +,0x4500 +,0xD380 +,0xFFE2 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0F80 +,0xDB80 +,0x21C0 +,0xFFCC +,0x0000 +,0xC680 +,0x0540 +,0x0023 +,0x33C0 +,0xDAC0 +,0x5900 +,0xFFDA +,0x0AC0 +,0xDF80 +,0x1940 +,0xFFF7 +,0x7FFF +,0x50C3 +,0x47FA +,0x4026 +,0x392C +,0x32F5 +,0x2D6A +,0x287A +,0x2413 +,0x2027 +,0x1CA8 +,0x198A +,0x16C3 +,0x1449 +,0x1214 +,0x101D +,0x0E5D +,0x0CCD +,0x0B68 +,0x0A2B +,0x0910 +,0x0813 +,0x0015 +,0x0002 +,0x0080 +,0x2848 +,0x051F +,0x0001 +,0x0010 +,0xFC40 +,0xFC40 +,0xFD94 +,0xFD80 +,0xFE80 +,0xFE80 +,0xFE7C +,0xFE7F +,0x02F4 +,0x0001 +,0x0080 +,0x0080 +,0x1000 +,0x0080 +,0x1000 +,0x1000 +,0x0400 +,0x599A +,0x199A +,0x0666 +,0x0021 +,0x2000 +,0x2000 +,0x2000 +,0xFFE4 +,0x0032 +,0x000A +,0x2000 +,0x4000 +,0x0800 +,0x0400 +,0x000C +,0x0005 +,0x000C +,0x0038 +,0x01A7 +,0x4000 +,0x0143 +,0x4009 +,0x0000 +,0x0000 +,0x0929 +,0x4020 +,0x0721 +,0x4041 +,0x0755 +,0x4052 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0x0000 +,0xFFD5 +,0x0001 +,0x0375 +,0x001E +,0x0AAB +,0x2000 +,0x2AAB +,0x0040 +,0x0005 +,0x001E +,0x0001 +,0xFEE0 +,0xFED8 +,0xFED8 +,0x0000 +,0x0040 +,0x40A2 +,0x0000 +}; + +const unsigned short bin_hw_coeff[] = { +0x0000 +,0x0027 +,0xfffd +,0xfffc +,0x0002 +,0x000a +,0x0005 +,0xfff4 +,0xffed +,0x0004 +,0x0024 +,0x0018 +,0xffd8 +,0xffb1 +,0x0006 +,0x00cd +,0x0179 +,0x0001 +,0xfffd +,0x0004 +,0x0000 +,0x000b +,0xffe0 +,0x0047 +,0xff75 +,0x0134 +,0x04c4 +,0xff9c +,0x000f +,0x0007 +,0xfff7 +,0x0006 +,0x0001 +,0x0008 +,0xffdf +,0x005d +,0xff18 +,0x034a +,0xff81 +,0x03d9 +,0x00a6 +,0xfffe +,0x0012 +,0xffa6 +,0x0000 +}; diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h new file mode 100755 index 000000000000..43ba9d68ad27 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h @@ -0,0 +1,59 @@ +/* mt6628_fm.h + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6628 FM Radio Driver -- head file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MT6628_FM_H__ +#define __MT6628_FM_H__ + +#include "fm_typedef.h" + +//#define FM_PowerOn_with_ShortAntenna +#define MT6628_RSSI_TH_LONG 0xFF01 //FM radio long antenna RSSI threshold(11.375dBuV) +#define MT6628_RSSI_TH_SHORT 0xFEE0 //FM radio short antenna RSSI threshold(-1dBuV) +#define MT6628_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) +#define MT6628_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ +#define MT6628_SCAN_CH_SIZE 40 //FM radio scan max channel size +#define MT6628_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special +#define MT6628_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) +#define MT6628_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) +#define MT6628_DEEMPHASIS_50us TRUE + +#define MT6628_SLAVE_ADDR 0xE0 //0x70 7-bit address +#define MT6628_MAX_COUNT 100 + +#ifdef MTK_FM_50KHZ_SUPPORT +#define MT6628_SCANTBL_SIZE 26 //16*uinit16_t +#else +#define MT6628_SCANTBL_SIZE 16 //16*uinit16_t +#endif + +#define AFC_ON 0x01 +#if AFC_ON +#define FM_MAIN_CTRL_INIT 0x480 +#else +#define FM_MAIN_CTRL_INIT 0x080 +#endif + +#define ext_clk //if define ext_clk use external reference clock or mask will use internal +#define MT6628_DEV "MT6628" + +#endif //end of #ifndef __MT6628_FM_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h new file mode 100755 index 000000000000..96b42b337496 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h @@ -0,0 +1,50 @@ +#ifndef __MT6628_FM_CMD_H__ +#define __MT6628_FM_CMD_H__ + +#include +#include "fm_typedef.h" + +/* FM basic-operation's opcode */ +#define FM_BOP_BASE (0x80) +enum { + FM_WRITE_BASIC_OP = (FM_BOP_BASE + 0x00), + FM_UDELAY_BASIC_OP = (FM_BOP_BASE + 0x01), + FM_RD_UNTIL_BASIC_OP = (FM_BOP_BASE + 0x02), + FM_MODIFY_BASIC_OP = (FM_BOP_BASE + 0x03), + FM_MSLEEP_BASIC_OP = (FM_BOP_BASE + 0x04), + FM_MAX_BASIC_OP = (FM_BOP_BASE + 0x05) +}; + +/* FM BOP's size */ +#define FM_WRITE_BASIC_OP_SIZE (3) +#define FM_UDELAY_BASIC_OP_SIZE (4) +#define FM_RD_UNTIL_BASIC_OP_SIZE (5) +#define FM_MODIFY_BASIC_OP_SIZE (5) +#define FM_MSLEEP_BASIC_OP_SIZE (4) + +fm_s32 mt6628_pwrup_fpga_on(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_pwrup_digital_init(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_pwrdown(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_rampdown(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_u16 chan_para); +fm_s32 mt6628_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6628_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq); +fm_s32 mt6628_cqi_get(fm_u8 *buf, fm_s32 buf_size); +fm_s32 mt6628_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr); +fm_s32 mt6628_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value); +fm_s32 mt6628_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6628_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6628_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6628_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len); +fm_s32 mt6628_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 *freq, fm_s32 cnt, fm_s32 type); + +/* + * fm_get_channel_space - get the spcace of gived channel + * @freq - value in 760~1080 or 7600~10800 + * + * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0 + */ +extern fm_s32 fm_get_channel_space(int freq); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h new file mode 100755 index 000000000000..d4f571db933e --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h @@ -0,0 +1,98 @@ +#ifndef __MT6628_FM_LIB_H__ +#define __MT6628_FM_LIB_H__ + +#include "fm_typedef.h" + +enum { + DSPPATCH = 0xFFF9, + USDELAY = 0xFFFA, + MSDELAY = 0xFFFB, + HW_VER = 0xFFFD, + POLL_N = 0xFFFE, //poling check if bit(n) is '0' + POLL_P = 0xFFFF, //polling check if bit(n) is '1' +}; + +enum { + FM_PUS_DSPPATCH = DSPPATCH, + FM_PUS_USDELAY = USDELAY, + FM_PUS_MSDELAY = MSDELAY, + FM_PUS_HW_VER = HW_VER, + FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0' + FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1' + FM_PUS_MAX +}; + +enum { + DSP_PATH = 0x02, + DSP_COEFF = 0x03, + DSP_HW_COEFF = 0x04 +}; + +enum IMG_TYPE { + IMG_WRONG = 0, + IMG_ROM, + IMG_PATCH, + IMG_COEFFICIENT, + IMG_HW_COEFFICIENT +}; + +enum { + mt6628_E1 = 0, + mt6628_E2 +}; + +enum { + FM_LONG_ANA = 0, + FM_SHORT_ANA +}; + +enum { + MT6628_I2S_ON = 0, + MT6628_I2S_OFF +}; + +enum { + MT6628_I2S_MASTER = 0, + MT6628_I2S_SLAVE +}; + +enum { + MT6628_I2S_32K = 0, + MT6628_I2S_44K, + MT6628_I2S_48K +}; +/* +struct mt6628_fm_i2s_info { + fm_s32 status; + fm_s32 mode; + fm_s32 rate; +}; +*/ +struct mt6628_fm_cqi { + fm_u16 ch; + fm_u16 rssi; + fm_u16 reserve; +}; + +struct adapt_fm_cqi { + fm_s32 ch; + fm_s32 rssi; + fm_s32 reserve; +}; + +struct mt6628_full_cqi { + fm_u16 ch; + fm_u16 rssi; + fm_u16 pamd; + fm_u16 pr; + fm_u16 fpamd; + fm_u16 mr; + fm_u16 atdc; + fm_u16 prx; + fm_u16 atdev; + fm_u16 smg; // soft-mute gain + fm_u16 drssi; // delta rssi +}; + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h new file mode 100755 index 000000000000..c7337fc16abc --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h @@ -0,0 +1,68 @@ +/* mt6626_fm_ctrl_link.h + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6626 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if 0 +#ifndef __MT6628_FM_LINK_H__ +#define __MT6628_FM_LINK_H__ + +#include +#include "fm_link.h" +#include "fm_utils.h" + +#define RX_BUF_SIZE 128 +#define TX_BUF_SIZE 1024 + +#define SW_RETRY_CNT (1) +#define SW_RETRY_CNT_MAX (5) +#define SW_WAIT_TIMEOUT_MAX (100) + +// FM operation timeout define for error handle +#define TEST_TIMEOUT (3) +#define FSPI_EN_TIMEOUT (3) +#define FSPI_MUXSEL_TIMEOUT (3) +#define FSPI_RD_TIMEOUT (3) +#define FSPI_WR_TIMEOUT (3) +#define I2C_RD_TIMEOUT (3) +#define I2C_WR_TIMEOUT (3) +#define EN_TIMEOUT (3) +#define RST_TIMEOUT (3) +#define TUNE_TIMEOUT (3) +#define SM_TUNE_TIMEOUT (6) +#define SEEK_TIMEOUT (15) +#define SCAN_TIMEOUT (15) //usualy scan will cost 10 seconds +#define RDS_RX_EN_TIMEOUT (3) +#define RDS_DATA_TIMEOUT (100) +#define RAMPDOWN_TIMEOUT (3) +#define MCUCLK_TIMEOUT (3) +#define MODEMCLK_TIMEOUT (3) +#define RDS_TX_TIMEOUT (3) +#define PATCH_TIMEOUT (3) +#define COEFF_TIMEOUT (3) +#define HWCOEFF_TIMEOUT (3) +#define ROM_TIMEOUT (3) + +struct fm_link_event { + struct fm_flag_event *ln_event; + struct fm_res_ctx result; // seek/scan/read/RDS +}; +#endif +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h new file mode 100755 index 000000000000..d4ab3c8c188a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h @@ -0,0 +1,90 @@ +#ifndef __MT6628_FM_REG_H__ +#define __MT6628_FM_REG_H__ + +enum MT6628_REG{ + FM_MAIN_CG1_CTRL = 0x60, + FM_MAIN_CG2_CTRL = 0x61, + FM_MAIN_HWVER = 0x62, + FM_MAIN_CTRL = 0x63, + FM_CHANNEL_SET = 0x65, + FM_MAIN_CFG1 = 0x66, + FM_MAIN_CFG2 = 0x67, + FM_MAIN_MCLKDESENSE = 0x38, + FM_MAIN_INTR = 0x69, + FM_MAIN_INTRMASK = 0x6A, + FM_MAIN_EXTINTRMASK = 0x6B, + FM_RSSI_IND = 0x6C, + FM_RSSI_TH = 0x6D, + FM_MAIN_RESET = 0x6E, + FM_MAIN_CHANDETSTAT = 0x6F, + FM_RDS_CFG0 = 0x80, + FM_RDS_INFO = 0x81, + FM_RDS_DATA_REG = 0x82, + FM_RDS_GOODBK_CNT = 0x83, + FM_RDS_BADBK_CNT = 0x84, + FM_RDS_PWDI = 0x85, + FM_RDS_PWDQ = 0x86, + FM_RDS_FIFO_STATUS0 = 0x87, + FM_FT_CON9 = 0x8F, + FM_DSP_PATCH_CTRL = 0x90, + FM_DSP_PATCH_OFFSET = 0x91, + FM_DSP_PATCH_DATA = 0x92, + FM_DSP_MEM_CTRL4 = 0x93, + FM_ADDR_PAMD = 0xB4, + FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6, + FM_RDS_POINTER = 0xF0, +}; + +//RDS_BDGRP_ABD_CTRL_REG +enum{ + BDGRP_ABD_EN = 0x0001, + BER_RUN = 0x2000 +}; +#define FM_DAC_CON1 0x83 +#define FM_DAC_CON2 0x84 +#define FM_FT_CON0 0x86 +enum{ + FT_EN = 0x0001 +}; + +#define FM_I2S_CON0 0x90 +enum{ + I2S_EN = 0x0001, + FORMAT = 0x0002, + WLEN = 0x0004, + I2S_SRC = 0x0008 +}; + +//FM_MAIN_CTRL +enum{ + TUNE = 0x0001, + SEEK = 0x0002, + SCAN = 0x0004, + CQI_READ = 0x0008, + RDS_MASK = 0x0010, + MUTE = 0x0020, + RDS_BRST = 0x0040, + RAMP_DOWN = 0x0100, +}; + +//FM_MAIN_INTR +enum{ + FM_INTR_STC_DONE = 0x0001, + FM_INTR_IQCAL_DONE = 0x0002, + FM_INTR_DESENSE_HIT = 0x0004, + FM_INTR_CHNL_CHG = 0x0008, + FM_INTR_SW_INTR = 0x0010, + FM_INTR_RDS = 0x0020 +}; + +enum{ + ANTENNA_TYPE = 0x0010, //0x61 D4, 0:long, 1:short + ANALOG_I2S = 0x0080, //0x61 D7, 0:lineout, 1:I2S + DE_EMPHASIS = 0x1000, //0x61 D12,0:50us, 1:75 us +}; + +#define OSC_FREQ_BITS 0x0070 //0x60 bit4~6 +#define OSC_FREQ_MASK (~OSC_FREQ_BITS) + +#endif //__MT6628_FM_REG_H__ + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c new file mode 100755 index 000000000000..799ed11cb59b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c @@ -0,0 +1,915 @@ +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_rds.h" +#include "fm_config.h" +#include "fm_link.h" + +#include "mt6628_fm_reg.h" +//#include "mt6628_fm_link.h" +#include "mt6628_fm.h" +#include "mt6628_fm_cmd.h" +#include "mt6628_fm_cust_cfg.h" + +extern fm_cust_cfg mt6628_fm_config; + +static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_WRITE_BASIC_OP; + buf[1] = FM_WRITE_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((value) & 0x00FF); + buf[4] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + + return (FM_WRITE_BASIC_OP_SIZE + 2); +} + + +static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_UDELAY_BASIC_OP; + buf[1] = FM_UDELAY_BASIC_OP_SIZE; + buf[2] = (fm_u8)((value) & 0x000000FF); + buf[3] = (fm_u8)((value >> 8) & 0x000000FF); + buf[4] = (fm_u8)((value >> 16) & 0x000000FF); + buf[5] = (fm_u8)((value >> 24) & 0x000000FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return (FM_UDELAY_BASIC_OP_SIZE + 2); +} + + +static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_RD_UNTIL_BASIC_OP; + buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask) & 0x00FF); + buf[4] = (fm_u8)((mask >> 8) & 0x00FF); + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_RD_UNTIL_BASIC_OP_SIZE + 2); +} + + +static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_MODIFY_BASIC_OP; + buf[1] = FM_MODIFY_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (fm_u8)((mask_and) & 0x00FF); + buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF); + buf[5] = (fm_u8)((mask_or) & 0x00FF); + buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return (FM_MODIFY_BASIC_OP_SIZE + 2); +} + +#if 0 +static fm_s32 fm_bop_msleep(fm_u32 value, fm_u8 *buf, fm_s32 size) +{ + if (size < (FM_MSLEEP_BASIC_OP_SIZE + 2)) { + return (-1); + } + + if (buf == NULL) { + return (-2); + } + + buf[0] = FM_MSLEEP_BASIC_OP; + buf[1] = FM_MSLEEP_BASIC_OP_SIZE; + buf[2] = (fm_u8)((value) & 0x000000FF); + buf[3] = (fm_u8)((value >> 8) & 0x000000FF); + buf[4] = (fm_u8)((value >> 16) & 0x000000FF); + buf[5] = (fm_u8)((value >> 24) & 0x000000FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return (FM_MSLEEP_BASIC_OP_SIZE + 2); +} +#endif + +/* +inline fm_s32 fm_get_channel_space(fm_s32 freq) +{ + if ((freq >= 760) && (freq <= 1080)) { + return 0; + } else if ((freq >= 7600) && (freq <= 10800)) { + return 1; + } else { + return -1; + } +} +*/ + +fm_s32 mt6628_pwrup_fpga_on(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Turn on Central Bias + FC + pkt_size += fm_bop_write(0x01, 0x4A00, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(30000, &buf[pkt_size], buf_size - pkt_size);//delay 30ms + pkt_size += fm_bop_write(0x01, 0x6A00, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms + pkt_size += fm_bop_write(0x02, 0x099C, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0x6B82, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x04, 0x0142, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x05, 0x00E7, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0A, 0x0060, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0C, 0xAF8F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0D, 0x0888, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x10, 0x0E8D, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x27, 0x0104, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0e, 0x0040, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0x9860, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3F, 0xAD16, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x06, 0x0125, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x08, 0x15B8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x00, 0x0167, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3A, 0x0004, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x25, 0x0403, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x22, 0x9980, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x25, 0x0803, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x1E, 0x0863, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms + pkt_size += fm_bop_write(0x1E, 0x0865, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms + pkt_size += fm_bop_write(0x1E, 0x0871, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x2A, 0x1020, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms + pkt_size += fm_bop_write(0x00, 0x01E7, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms + pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x1B, 0x0095, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(200000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms + pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x00, 0x0167, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0x6B8A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms + pkt_size += fm_bop_write(0x00, 0xC167, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0C, 0xAF8F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(30000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms + pkt_size += fm_bop_write(0x00, 0xF167, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x37, 0x2590, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x09, 0x2964, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x2E, 0x0008, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x11, 0x37D4, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x2B, 0x0032, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x2C, 0x0019, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x71, 0x607F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x72, 0x878F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x73, 0x07C3, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x6D, 0x1AB2, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x9C, 0x0040, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xB4, 0x8810, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xB8, 0x006A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xBB, 0x006B, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xCB, 0x00B3, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xE0, 0xA301, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xE4, 0x008F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x9E, 0x2B24, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xCC, 0x0886, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xDC, 0x036A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xDD, 0x836A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x0F, 0x1AA8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms + pkt_size += fm_bop_write(0x63, 0x0480, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms + pkt_size += fm_bop_write(0x63, 0x0481, &buf[pkt_size], buf_size - pkt_size); + + pkt_size += fm_bop_write(0x6C, 0x0020, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x45, 0x1FFF, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x25, 0x040F, &buf[pkt_size], buf_size - pkt_size); + + pkt_size += fm_bop_write(0x28, 0x7E57, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x11, 0x37DC, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x07, 0x1140, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x27, 0x005C, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x42, 0x0016, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x44, 0x006F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x46, 0x1DEF, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x47, 0x0210, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x55, 0x0001, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x54, 0x8001, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0xA0, 0xD0B2, &buf[pkt_size], buf_size - pkt_size); + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6628_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + fm_u16 de_emphasis; + fm_u16 osc_freq; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + de_emphasis = mt6628_fm_config.rx_cfg.deemphasis;//MT6628fm_cust_config_fetch(FM_CFG_RX_DEEMPHASIS); + de_emphasis &= 0x0001; //rang 0~1 + osc_freq = mt6628_fm_config.rx_cfg.osc_freq;//MT6628fm_cust_config_fetch(FM_CFG_RX_OSC_FREQ); + osc_freq &= 0x0007; //rang 0~5 + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //FM Digital Clock enable + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000 + pkt_size += fm_bop_write(0x60, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 60 0001 + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3ms + pkt_size += fm_bop_write(0x60, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 60 0003 + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size);//wr 60 0007 + pkt_size += fm_bop_modify(0x70, 0xFFBF, 0x0040, &buf[pkt_size], buf_size - pkt_size); // wr 70 D6 = 1 + //no low power mode, analog line in, long antenna + pkt_size += fm_bop_modify(0x61, 0xFF63, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x60, OSC_FREQ_MASK, (osc_freq << 4), &buf[pkt_size], buf_size - pkt_size); + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_patch_download - Wholechip FM Power Up: step 3, download patch to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6628_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_PATCH_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + + +/* + * mt6628_coeff_download - Wholechip FM Power Up: step 3,download coeff to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6628_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_COEFF_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + + +/* + * mt6628_hwcoeff_download - Wholechip FM Power Up: step 3,download hwcoeff to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6628_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_HWCOEFF_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + + +/* + * mt6628_rom_download - Wholechip FM Power Up: step 3,download rom to f/w, + * @buf - target buf + * @buf_size - buffer size + * @seg_num - total segments that this patch divided into + * @seg_id - No. of Segments: segment that will now be sent + * @src - patch source buffer + * @seg_len - segment size: segment that will now be sent + * return package size + */ +fm_s32 mt6628_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len) +{ + fm_s32 pkt_size = 0; + fm_u8 *dst = NULL; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ROM_DOWNLOAD_OPCODE; + pkt_size = 4; + + buf[pkt_size++] = seg_num; + buf[pkt_size++] = seg_id; + + if (seg_len > (buf_size - pkt_size)) { + return -1; + } + + dst = &buf[pkt_size]; + pkt_size += seg_len; + + //copy patch to tx buffer + while (seg_len--) { + *dst = *src; + //printk(KERN_ALERT "%02x ", *dst); + src++; + dst++; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + return pkt_size; +} + + +/* + * mt6628_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6628_pwrup_digital_init(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon + pkt_size += fm_bop_write(0x6A, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6A 2100 + pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6B 2100 + pkt_size += fm_bop_modify(0x60, 0xFFF7, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 60 D3=1 + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 61 D1=1 + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 61 D0=0 + pkt_size += fm_bop_udelay(200000, &buf[pkt_size], buf_size - pkt_size);//delay 200ms + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//Poll 64[0~4] = 2 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6628_pwrdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_ENABLE_OPCODE; + pkt_size = 4; + + //Disable HW clock control + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size);//wr 60 330F + //Reset ASIP + pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 61 0001 + //digital core + digital rgf reset + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0 + //Disable all clock + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000 + //Reset rgfrf + pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 60 4000 + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +fm_s32 mt6628_rampdown(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_RAMPDOWN_OPCODE; + pkt_size = 4; + + //Clear DSP state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0 + //Set DSP ramp down state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 1 + //@Wait for STC_DONE interrupt@ + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Clear DSP ramp down state + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 0 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +fm_s32 mt6628_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_u16 chan_para) +{ + //#define FM_TUNE_USE_POLL + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + freq = (freq - 6400) * 2 / 10; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_TUNE_OPCODE; + pkt_size = 4; + + //Set desired channel & channel parameter +#ifdef FM_TUNE_USE_POLL + pkt_size += fm_bop_write(0x6A, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x6B, 0x0000, &buf[pkt_size], buf_size - pkt_size); +#endif + pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20) + //channel para setting, D15~D12, D15: ATJ, D13: HL, D12: FA + pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0x0FFF, (chan_para << 12), &buf[pkt_size], buf_size - pkt_size); + //Enable hardware controlled tuning sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1 + //Wait for STC_DONE interrupt +#ifdef FM_TUNE_USE_POLL + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 +#endif + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_full_cqi_req - execute request cqi info action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 7600 ~ 10800, freq array + * @cnt - channel count + * @type - request type, 1: a single channel; 2: multi channel; 3:multi channel with 100Khz step; 4: multi channel with 50Khz step + * + * return package size + */ +fm_s32 mt6628_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 *freq, fm_s32 cnt, fm_s32 type) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SOFT_MUTE_TUNE_OPCODE; + pkt_size = 4; + + switch (type) { + case 1: + buf[pkt_size] = 0x0001; + pkt_size++; + buf[pkt_size] = (fm_u8)((*freq) & 0x00FF); + pkt_size++; + buf[pkt_size] = (fm_u8)((*freq >> 8) & 0x00FF); + pkt_size++; + break; + case 2: + buf[pkt_size] = 0x0002; + pkt_size++; + break; + case 3: + buf[pkt_size] = 0x0003; + pkt_size++; + break; + case 4: + buf[pkt_size] = 0x0004; + pkt_size++; + break; + default: + buf[pkt_size] = (fm_u16)type; + pkt_size++; + break; + } + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_seek - execute seek action, + * @buf - target buf + * @buf_size - buffer size + * @seekdir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6628_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + if (0 == fm_get_channel_space(max_freq)) { + max_freq *= 10; + } + + if (0 == fm_get_channel_space(min_freq)) { + min_freq *= 10; + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SEEK_OPCODE; + pkt_size = 4; + + //Program seek direction + if (seekdir == 0) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //Program scan channel spacing + if (space == 1) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else if (space == 2) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } else if (space == 4) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100 + } + + //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap + //0x66[9:0] freq upper bound + + max_freq = (max_freq - 6400) * 2 / 10; + + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + //0x67[9:0] freq lower bound + + min_freq = (min_freq - 6400) * 2 / 10; + + pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //Enable hardware controlled seeking sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, SEEK, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + //Wait for STC_DONE interrupt + //pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + //pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +/* + * mt6628_scan - execute scan action, + * @buf - target buf + * @buf_size - buffer size + * @scandir - 0=seek up, 1=seek down + * @space - step, 50KHz:001, 100KHz:010, 200KHz:100 + * @max_freq - upper bound + * @min_freq - lower bound + * return package size + */ +fm_s32 mt6628_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + if (0 == fm_get_channel_space(max_freq)) { + max_freq *= 10; + } + if (0 == fm_get_channel_space(min_freq)) { + min_freq *= 10; + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SCAN_OPCODE; + pkt_size = 4; + + //Program seek direction + if (scandir == 0) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up + } else { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down + } + + //Program scan channel spacing + if (space == 1) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001 + } else if (space == 2) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010 + } else if (space == 4) { + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100 + } + + //disable wrap , if it is auto scan function, 0x66[11] 0=no wrarp, 1=wrap + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 0, no wrap + //0x66[9:0] freq upper bound + + max_freq = (max_freq - 6400) * 2 / 10; + + pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size); + //0x67[9:0] freq lower bound + + min_freq = (min_freq - 6400) * 2 / 10; + + pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size); + //Enable hardware controlled scanning sequence + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, SCAN, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1 + //Wait for STC_DONE interrupt + //pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1 + //Write 1 clear the STC_DONE interrupt status flag + //pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +fm_s32 mt6628_cqi_get(fm_u8 *buf, fm_s32 buf_size) +{ + fm_s32 pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_SCAN_OPCODE; + pkt_size = 4; + + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 bit0~2 0 + pkt_size += fm_bop_modify(FM_MAIN_CTRL, ~CQI_READ, CQI_READ, &buf[pkt_size], buf_size - pkt_size);//wr 63 bit3 1 + + buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF); + buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +fm_s32 mt6628_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_READ_OPCODE; + buf[2] = 0x01; + buf[3] = 0x00; + buf[4] = addr; + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]); + return 5; +} + + +fm_s32 mt6628_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value) +{ + if (buf_size < TX_BUF_SIZE) { + return (-1); + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FSPI_WRITE_OPCODE; + buf[2] = 0x03; + buf[3] = 0x00; + buf[4] = addr; + buf[5] = (fm_u8)((value) & 0x00FF); + buf[6] = (fm_u8)((value >> 8) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + return 7; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c new file mode 100755 index 000000000000..002000cd03d8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c @@ -0,0 +1,279 @@ +/* fm_config.c + * + * (C) Copyright 2011 + * MediaTek + * hongcheng + * + * FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_patch.h" +#include "fm_config.h" +//#include "fm_cust_cfg.h" +#include "mt6628_fm_cust_cfg.h" +fm_cust_cfg mt6628_fm_config; +//static fm_s32 fm_index = 0; + +static fm_s32 MT6628fm_cust_config_print(fm_cust_cfg *cfg) +{ + WCN_DBG(FM_NTC | MAIN, "MT6628 rssi_l:\t%d\n", cfg->rx_cfg.long_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 rssi_s:\t%d\n", cfg->rx_cfg.short_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 pamd_th:\t%d\n", cfg->rx_cfg.pamd_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 mr_th:\t%d\n", cfg->rx_cfg.mr_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 atdc_th:\t%d\n", cfg->rx_cfg.atdc_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 prx_th:\t%d\n", cfg->rx_cfg.prx_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 atdev_th:\t%d\n", cfg->rx_cfg.atdev_th); + WCN_DBG(FM_NTC | MAIN, "MT6628 smg_th:\t%d\n", cfg->rx_cfg.smg_th); + WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis); + WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq); + + return 0; +} + +static fm_s32 MT6628cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg; + + if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_LONG_MT6628", &rx_cfg->long_ana_rssi_th))) + {//FMR_RSSI_TH_L = 0x0301 + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_SHORT_MT6628", &rx_cfg->short_ana_rssi_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DESENSE_RSSI_MT6628", &rx_cfg->desene_rssi_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PAMD_TH_MT6628", &rx_cfg->pamd_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_MR_TH_MT6628", &rx_cfg->mr_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDC_TH_MT6628", &rx_cfg->atdc_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PRX_TH_MT6628", &rx_cfg->prx_th))) + { + return ret; + } + /*else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDEV_TH_MT6628", &rx_cfg->atdev_th))) + { + return ret; + } */ + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_SMG_TH_MT6628", &rx_cfg->smg_th))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DEEMPHASIS_MT6628", &rx_cfg->deemphasis))) + { + return ret; + } + else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_OSC_FREQ_MT6628", &rx_cfg->osc_freq))) + { + return ret; + } + else + { + WCN_DBG(FM_WAR | MAIN, "MT6628 invalid key\n"); + return -1; + } +} + +static fm_s32 MT6628fm_cust_config_default(fm_cust_cfg *cfg) +{ + FMR_ASSERT(cfg); + + cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG_MT6628; + cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT_MT6628; + cfg->rx_cfg.desene_rssi_th = FM_RX_DESENSE_RSSI_MT6628; + cfg->rx_cfg.pamd_th = FM_RX_PAMD_TH_MT6628; + cfg->rx_cfg.mr_th = FM_RX_MR_TH_MT6628; + cfg->rx_cfg.atdc_th = FM_RX_ATDC_TH_MT6628; + cfg->rx_cfg.prx_th = FM_RX_PRX_TH_MT6628; + cfg->rx_cfg.smg_th = FM_RX_SMG_TH_MT6628; + cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS_MT6628; + cfg->rx_cfg.osc_freq = FM_RX_OSC_FREQ_MT6628; + + return 0; +} + +static fm_s32 MT6628fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg) +{ + fm_s32 ret = 0; + fm_s8 *buf = NULL; + fm_s32 file_len = 0; + + if (!(buf = fm_zalloc(4096))) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + return -ENOMEM; + } + +// fm_index = 0; + + file_len = fm_file_read(filename, buf, 4096, 0); + + if (file_len <= 0) { + ret = -1; + goto out; + } + + ret = cfg_parser(buf, MT6628cfg_item_handler, cfg); + +out: + + if (buf) { + fm_free(buf); + } + + return ret; +} +#define MT6628_FM_CUST_CFG_PATH "etc/fmr/fm_cust.cfg" +fm_s32 MT6628fm_cust_config_setup(const fm_s8 *filepath) +{ + fm_s32 ret = 0; + fm_s8 *filep = NULL; + fm_s8 file_path[51] = {0}; + + MT6628fm_cust_config_default(&mt6628_fm_config); + WCN_DBG(FM_NTC | MAIN, "MT6628 FM default config\n"); + MT6628fm_cust_config_print(&mt6628_fm_config); + + if (!filepath) { + filep = MT6628_FM_CUST_CFG_PATH; + } else { + memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath)); + filep = file_path; + trim_path(&filep); + } + + ret = MT6628fm_cust_config_file(filep, &mt6628_fm_config); + WCN_DBG(FM_NTC | MAIN, "MT6628 FM cust config\n"); + MT6628fm_cust_config_print(&mt6628_fm_config); + + return ret; +} +fm_u16 MT6628fm_cust_config_fetch(enum fm_cust_cfg_op op_code) +{ +#if 0 + fm_u16 tmp = 0; + fm_s32 i; + static fm_s32 fake_ch_idx = 0; + + switch (op_code) { + //For FM RX + case FM_CFG_RX_RSSI_TH_LONG: { + tmp = mt6628_fm_config.rx_cfg.long_ana_rssi_th; + break; + } + case FM_CFG_RX_RSSI_TH_SHORT: { + tmp = mt6628_fm_config.rx_cfg.short_ana_rssi_th; + break; + } + case FM_CFG_RX_CQI_TH: { + tmp = mt6628_fm_config.rx_cfg.cqi_th; + break; + } + case FM_CFG_RX_MR_TH: { + tmp = mt6628_fm_config.rx_cfg.mr_th; + break; + } + case FM_CFG_RX_SMG_TH: { + tmp = mt6628_fm_config.rx_cfg.smg_th; + break; + } + case FM_CFG_RX_SCAN_CH_SIZE: { + tmp = mt6628_fm_config.rx_cfg.scan_ch_size; + break; + } + case FM_CFG_RX_SEEK_SPACE: { + tmp = mt6628_fm_config.rx_cfg.seek_space; + break; + } + case FM_CFG_RX_BAND: { + tmp = mt6628_fm_config.rx_cfg.band; + break; + } + case FM_CFG_RX_BAND_FREQ_L: { + tmp = mt6628_fm_config.rx_cfg.band_freq_l; + break; + } + case FM_CFG_RX_BAND_FREQ_H: { + tmp = mt6628_fm_config.rx_cfg.band_freq_h; + break; + } + case FM_CFG_RX_SCAN_SORT: { + tmp = mt6628_fm_config.rx_cfg.scan_sort; + break; + } + case FM_CFG_RX_FAKE_CH_NUM: { + tmp = mt6628_fm_config.rx_cfg.fake_ch_num; + break; + } + case FM_CFG_RX_FAKE_CH: { + tmp = mt6628_fm_config.rx_cfg.fake_ch[fake_ch_idx]; + i = (mt6628_fm_config.rx_cfg.fake_ch_num > 0) ? mt6628_fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX; + fake_ch_idx++; + fake_ch_idx = fake_ch_idx % i; + break; + } + case FM_CFG_RX_FAKE_CH_RSSI: { + tmp = mt6628_fm_config.rx_cfg.fake_ch_rssi_th; + break; + } + case FM_CFG_RX_DEEMPHASIS: { + tmp = mt6628_fm_config.rx_cfg.deemphasis; + break; + } + case FM_CFG_RX_OSC_FREQ: { + tmp = mt6628_fm_config.rx_cfg.osc_freq; + break; + } + //For FM TX + case FM_CFG_TX_SCAN_HOLE_LOW: { + tmp = mt6628_fm_config.tx_cfg.scan_hole_low; + break; + } + case FM_CFG_TX_SCAN_HOLE_HIGH: { + tmp = mt6628_fm_config.tx_cfg.scan_hole_high; + break; + } + case FM_CFG_TX_PWR_LEVEL: { + tmp = mt6628_fm_config.tx_cfg.power_level; + break; + } + default: + break; + } + + WCN_DBG(FM_DBG | MAIN, "mt6628_cust cfg %d: 0x%04x\n", op_code, tmp); +#endif + return 0; +} diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c new file mode 100755 index 000000000000..4e69b9e046ef --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c @@ -0,0 +1,55 @@ +/* mt6628_fm_eint.c + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6628 FM Radio Driver -- EINT functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if 0 +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_eint.h" + +fm_s32 fm_enable_eint(void) +{ + return 0; +} + +fm_s32 fm_disable_eint(void) +{ + return 0; +} + +fm_s32 fm_request_eint(void (*parser)(void)) +{ + WCN_DBG(FM_NTC|EINT,"%s\n", __func__); + + mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser); + + return 0; +} + +fm_s32 fm_eint_pin_cfg(fm_s32 mode) +{ + return 0; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c new file mode 100755 index 000000000000..e101b7a9def7 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c @@ -0,0 +1,1741 @@ +#include +#include +#include + +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_patch.h" +#include "fm_utils.h" +#include "fm_link.h" +#include "fm_config.h" +#include "fm_private.h" + +#include "mt6628_fm_reg.h" +#include "mt6628_fm.h" +//#include "mt6628_drv_dsp.h" +//#include "mt6628_fm_link.h" +#include "mt6628_fm_lib.h" +#include "mt6628_fm_cmd.h" +#include "mt6628_fm_cust_cfg.h" +extern fm_cust_cfg mt6628_fm_config; + +#define MT6628_FM_PATCH_PATH "/etc/firmware/mt6628/mt6628_fm_patch.bin" +#define MT6628_FM_COEFF_PATH "/etc/firmware/mt6628/mt6628_fm_coeff.bin" +#define MT6628_FM_HWCOEFF_PATH "/etc/firmware/mt6628/mt6628_fm_hwcoeff.bin" +#define MT6628_FM_ROM_PATH "/etc/firmware/mt6628/mt6628_fm_rom.bin" + +static struct fm_patch_tbl mt6628_patch_tbl[5] = { + {FM_ROM_V1, "/etc/firmware/mt6628/mt6628_fm_v1_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "/etc/firmware/mt6628/mt6628_fm_v2_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "/etc/firmware/mt6628/mt6628_fm_v3_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "/etc/firmware/mt6628/mt6628_fm_v4_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "/etc/firmware/mt6628/mt6628_fm_v5_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v5_coeff.bin", NULL, NULL}, +}; + +static struct fm_hw_info mt6628_hw_info = { + .chip_id = 0x00006628, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_i2s_info mt6628_i2s_inf = { + .status = 0, //i2s off + .mode = 0, //slave mode + .rate = 48000, //48000 sample rate +}; + +#define PATCH_SEG_LEN 512 + +static fm_u8 *cmd_buf = NULL; +static struct fm_lock *cmd_buf_lock = NULL; +static struct fm_callback *fm_cb_op; +static struct fm_res_ctx *res = NULL; +//static fm_s32 Chip_Version = mt6628_E1; + +//static fm_bool rssi_th_set = fm_false; + +#ifdef MT6628_FM_FPGA +#undef MT6628_FM_USE_6626EVB +#endif + +#ifdef MTK_FM_50KHZ_SUPPORT +static struct fm_fifo *cqi_fifo = NULL; +#endif +static fm_s32 mt6628_is_dese_chan(fm_u16 freq); +static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg); +static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg); +static fm_u16 mt6628_chan_para_get(fm_u16 freq); +static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi); +static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample); +static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid); +static fm_s32 mt6628_pwron(fm_s32 data) +{ + /*//Turn on FM on 6628 chip by WMT driver + if(MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK)){ + WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK Fail!\n"); + return -FM_ELINK; + }else{ + WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK OK!\n"); + //return 0; + }*/ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM)) { + WCN_DBG(FM_ALT | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } else { + WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n"); + return 0; + } +} + + +static fm_s32 mt6628_pwroff(fm_s32 data) +{ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM)) { + WCN_DBG(FM_ALT | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } else { + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; + } +} + +static fm_s32 Delayms(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data); + msleep(data); + return 0; +} + +static fm_s32 Delayus(fm_u32 data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data); + udelay(data); + return 0; +} + +fm_s32 mt6628_get_read_result(struct fm_res_ctx* result) +{ + FMR_ASSERT(result); + res = result; + + return 0; +} + +static fm_s32 mt6628_read(fm_u8 addr, fm_u16 *val) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_get_reg(cmd_buf, TX_BUF_SIZE, addr); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_RD, SW_RETRY_CNT, FSPI_RD_TIMEOUT, mt6628_get_read_result); + + if (!ret && res) { + *val = res->fspi_rd; + } + + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +static fm_s32 mt6628_write(fm_u8 addr, fm_u16 val) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_set_reg(cmd_buf, TX_BUF_SIZE, addr, val); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_WR, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +static fm_s32 mt6628_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask) +{ + fm_s32 ret = 0; + fm_u16 val; + + ret = mt6628_read(addr, &val); + + if (ret) + return ret; + + val = ((val & (mask)) | bits); + ret = mt6628_write(addr, val); + + return ret; +} + +static fm_u16 mt6628_get_chipid(void) +{ + return 0x6628; +} + +/* MT6628_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static fm_s32 mt6628_SetAntennaType(fm_s32 type) +{ + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + mt6628_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) { + dataRead |= ANTENNA_TYPE; + } else { + dataRead &= (~ANTENNA_TYPE); + } + + mt6628_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static fm_s32 mt6628_GetAntennaType(void) +{ + fm_u16 dataRead; + + mt6628_read(FM_MAIN_CG2_CTRL, &dataRead); + WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long"); + + if (dataRead&ANTENNA_TYPE) + return FM_ANA_SHORT; //short antenna + else + return FM_ANA_LONG; //long antenna +} + + +static fm_s32 mt6628_Mute(fm_bool mute) +{ + fm_s32 ret = 0; + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + mt6628_read(FM_MAIN_CTRL, &dataRead); + + if (mute == 1) { + ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020); + } else { + ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF)); +} + + return ret; +} + + +/*static fm_s32 mt6628_set_RSSITh(fm_u16 TH_long, fm_u16 TH_short) +{ + mt6628_write(0xE2, 0x3072); + mt6628_write(0xE3, TH_long); + mt6628_write(0xE1, 0x0002); + Delayms(1); + mt6628_write(0xE2, 0x307A); + mt6628_write(0xE3, TH_short); + mt6628_write(0xE1, 0x0002); + + WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short); + return 0; +} +*/ +/* +static fm_s32 mt6628_set_SMGTh(fm_s32 ver, fm_u16 TH_smg) +{ + if (mt6628_E1 == ver) { + mt6628_write(0xE2, 0x321E); + mt6628_write(0xE3, TH_smg); + mt6628_write(0xE1, 0x0002); + } else { + mt6628_write(0xE2, 0x3218); + mt6628_write(0xE3, TH_smg); + mt6628_write(0xE1, 0x0002); + } + + WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg); + return 0; +} +*/ +static fm_s32 mt6628_RampDown(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 tmp; + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + + mt6628_read(FM_MAIN_INTRMASK, &tmp); + mt6628_write(FM_MAIN_INTRMASK, 0x0000); + mt6628_write(0x6B, 0x0000); + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_rampdown(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down failed\n"); + } + +#ifdef MT6628_FM_FPGA + Delayms(10); + mt6628_write(0x54, 0x0001); + mt6628_write(0x11, 0x37D4); + mt6628_write(0x54, 0x8000); +#endif + mt6628_write(0x6B, 0x2100); + mt6628_write(FM_MAIN_INTRMASK, tmp); + return ret; +} + +static fm_s32 mt6628_get_rom_version(void) +{ + fm_u16 tmp; + + //DSP rom code version request enable --- set 0x61 b15=1 + mt6628_set_bits(0x61, 0x8000, 0x7FFF); + + //Release ASIP reset --- set 0x61 b1=1 + mt6628_set_bits(0x61, 0x0002, 0xFFFD); + + //Enable ASIP power --- set 0x61 b0=0 + mt6628_set_bits(0x61, 0x0000, 0xFFFE); + + //Wait DSP code version ready --- wait 1ms + Delayus(1000); + + //Get FM DSP code version --- rd 0x83[15:8] + mt6628_read(0x83, &tmp); + tmp = (tmp >> 8); + + //DSP rom code version request disable --- set 0x61 b15=0 + mt6628_set_bits(0x61, 0x0000, 0x7FFF); + + //Reset ASIP --- set 0x61[1:0] = 1 + mt6628_set_bits(0x61, 0x0001, 0xFFFC); + + WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (fm_s32)tmp); + return (fm_s32)tmp; +} + +static fm_s32 mt6628_get_patch_path(fm_s32 ver, const fm_s8 **ppath) +{ + fm_s32 i; + fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]); + + //check if the ROM version is defined or not + for (i = 0; i < max; i++) { + if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].patch) == 0)) { + *ppath = mt6628_patch_tbl[i].patch; + WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n"); + return 0; + } + } + + + // the ROM version isn't defined, find a latest patch instead + for (i = max; i > 0; i--) { + if (fm_file_exist(mt6628_patch_tbl[i-1].patch) == 0) { + *ppath = mt6628_patch_tbl[i-1].patch; + WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n"); + return 1; + } + } + + // get path failed + WCN_DBG(FM_ERR | CHIP, "No valid patch file\n"); + return -FM_EPATCH; +} + + +static fm_s32 mt6628_get_coeff_path(fm_s32 ver, const fm_s8 **ppath) +{ + fm_s32 i; + fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]); + + //check if the ROM version is defined or not + for (i = 0; i < max; i++) { + if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].coeff) == 0)) { + *ppath = mt6628_patch_tbl[i].coeff; + WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n"); + return 0; + } + } + + + // the ROM version isn't defined, find a latest patch instead + for (i = max; i > 0; i--) { + if (fm_file_exist(mt6628_patch_tbl[i-1].coeff) == 0) { + *ppath = mt6628_patch_tbl[i-1].coeff; + WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n"); + return 1; + } + } + + // get path failed + WCN_DBG(FM_ERR | CHIP, "No valid coeff file\n"); + return -FM_EPATCH; +} + + +/* +* mt6628_DspPatch - DSP download procedure +* @img - source dsp bin code +* @len - patch length in byte +* @type - rom/patch/coefficient/hw_coefficient +*/ +static fm_s32 mt6628_DspPatch(const fm_u8 *img, fm_s32 len, enum IMG_TYPE type) +{ + fm_u8 seg_num; + fm_u8 seg_id = 0; + fm_s32 seg_len; + fm_s32 ret = 0; + fm_u16 pkt_size; + + FMR_ASSERT(img); + + if (len <= 0) { + return -1; + } + + seg_num = len / PATCH_SEG_LEN + 1; + WCN_DBG(FM_NTC | CHIP, "binary len:%d, seg num:%d\n", len, seg_num); + + switch (type) { + case IMG_ROM: + + for (seg_id = 0; seg_id < seg_num; seg_id++) { + seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN); + WCN_DBG(FM_NTC | CHIP, "rom,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_rom_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_ROM, SW_RETRY_CNT, ROM_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_rom_download failed\n"); + return ret; + } + } + + break; + case IMG_PATCH: + + for (seg_id = 0; seg_id < seg_num; seg_id++) { + seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN); + WCN_DBG(FM_NTC | CHIP, "patch,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_patch_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PATCH, SW_RETRY_CNT, PATCH_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_patch_download failed\n"); + return ret; + } + } + + break; + case IMG_HW_COEFFICIENT: + + for (seg_id = 0; seg_id < seg_num; seg_id++) { + seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN); + WCN_DBG(FM_NTC | CHIP, "hwcoeff,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_hwcoeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_HWCOEFF, SW_RETRY_CNT, HWCOEFF_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_hwcoeff_download failed\n"); + return ret; + } + } + + break; + case IMG_COEFFICIENT: + + for (seg_id = 0; seg_id < seg_num; seg_id++) { + seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN); + WCN_DBG(FM_NTC | CHIP, "coeff,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_coeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_COEFF, SW_RETRY_CNT, COEFF_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_coeff_download failed\n"); + return ret; + } + } + + break; + default: + break; + } + + return 0; +} + + +static fm_s32 mt6628_PowerUp(fm_u16 *chip_id, fm_u16 *device_id) +{ +#define PATCH_BUF_SIZE 4096*6 + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 tmp_reg = 0; + + const fm_s8 *path_patch = NULL; + const fm_s8 *path_coeff = NULL; + //const fm_s8 *path_hwcoeff = NULL; + //fm_s32 coeff_len = 0; + fm_s32 patch_len = 0; + fm_u8 *dsp_buf = NULL; + + FMR_ASSERT(chip_id); + FMR_ASSERT(device_id); + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + //Wholechip FM Power Up: step 1, FM Digital Clock enable + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_pwrup_clock_on(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_clock_on failed\n"); + return ret; + } + +#ifdef FM_DIGITAL_INPUT + mt6628_I2s_Setting(MT6628_I2S_ON, MT6628_I2S_SLAVE, MT6628_I2S_44K); + mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2); +#endif + + //Wholechip FM Power Up: step 2, read HW version + mt6628_read(0x62, &tmp_reg); + mt6628_read(0x62, &tmp_reg); + *chip_id = tmp_reg; + *device_id = tmp_reg; + mt6628_hw_info.chip_id = (fm_s32)tmp_reg; + WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if (mt6628_hw_info.chip_id != 0x6628) { + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n"); + return (-FM_EFW); + } + + mt6628_hw_info.eco_ver = (fm_s32)mtk_wcn_wmt_hwver_get(); + WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6628_hw_info.eco_ver); + mt6628_hw_info.eco_ver += 1; + + //get mt6628 DSP rom version + if ((ret = mt6628_get_rom_version()) >= 0) { + mt6628_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6628_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + } + + + //Wholechip FM Power Up: step 3, download patch + if (!(dsp_buf = fm_vmalloc(PATCH_BUF_SIZE))) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + ret = mt6628_get_patch_path(mt6628_hw_info.rom_ver, &path_patch); + patch_len = fm_file_read(path_patch, dsp_buf, PATCH_BUF_SIZE, 0); + mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_PATCH); + + ret = mt6628_get_coeff_path(mt6628_hw_info.rom_ver, &path_coeff); + patch_len = fm_file_read(path_coeff, dsp_buf, PATCH_BUF_SIZE, 0); + + mt6628_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); + mt6628_hw_info.patch_ver = (fm_s32)tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6628_hw_info.patch_ver); + + if (ret == 1) { + dsp_buf[4] = 0x00; //if we found rom version undefined, we should disable patch + dsp_buf[5] = 0x00; + } + + mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_COEFFICIENT); + mt6628_write(0x90, 0x0040); + mt6628_write(0x90, 0x0000); + + if (dsp_buf) { + fm_vfree(dsp_buf); + dsp_buf = NULL; + } + + //mt6628_check_dsp(); + + //Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_pwrup_digital_init(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_digital_init failed\n"); + return ret;; + } + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + //mt6628_check_dsp(); + +// rssi_th_set = fm_false; + return ret; +} + +static fm_s32 mt6628_PowerDown(void) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 dataRead; + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + /*SW work around for MCUFA issue. + *if interrupt happen before doing rampdown, DSP can't switch MCUFA back well. + * In case read interrupt, and clean if interrupt found before rampdown. + */ + mt6628_read(FM_MAIN_INTR, &dataRead); + + if (dataRead & 0x1) { + mt6628_write(FM_MAIN_INTR, dataRead);//clear status flag + } + + mt6628_RampDown(); + +#ifdef FM_DIGITAL_INPUT + mt6628_I2s_Setting(MT6628_I2S_OFF, MT6628_I2S_SLAVE, MT6628_I2S_44K); +#endif + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_pwrdown(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_pwrdown failed\n"); + return ret; + } + + //FIX_ME, disable ext interrupt + mt6628_write(FM_MAIN_EXTINTRMASK, 0x00); + +// rssi_th_set = fm_false; + return ret; +} + +static fm_bool mt6628_SetFreq(fm_u16 freq) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 chan_para = 0; + + fm_cb_op->cur_freq_set(freq); + + + //MCU clock adjust if need + if ((ret = mt6628_mcu_dese(freq, NULL)) < 0) + { + WCN_DBG(FM_ERR | MAIN, "mt6628_mcu_dese FAIL:%d\n", ret); + } + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); + + //GPS clock adjust if need + if ((ret = mt6628_gps_dese(freq, NULL)) < 0) + { + WCN_DBG(FM_ERR | MAIN, "mt6628_gps_dese FAIL:%d\n", ret); + } + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); + //start tune + if (FM_LOCK(cmd_buf_lock)) return fm_false; + +// if (fm_cb_op->chan_para_get) { + chan_para = mt6628_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (fm_s32)freq, (fm_s32)chan_para); +// } + + pkt_size = mt6628_tune(cmd_buf, TX_BUF_SIZE, freq, chan_para); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE | FLAG_TUNE_DONE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6628_tune failed\n"); + return ret; + } + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + + /* if (rssi_th_set == fm_false) { + mt6628_set_RSSITh(MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG), MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT)); + mt6628_set_SMGTh(Chip_Version, MT6628fm_cust_config_fetch(FM_CFG_RX_SMG_TH)); + rssi_th_set = fm_true; + }*/ + + return fm_true; +} + + +/* +* mt6628_Seek +* @pFreq - IN/OUT parm, IN start freq/OUT seek valid freq +* @seekdir - 0:up, 1:down +* @space - 1:50KHz, 2:100KHz, 4:200KHz +* return fm_true:seek success; fm_false:seek failed +*/ +static fm_bool mt6628_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space) +{ + fm_s32 ret = 0; + fm_u16 pkt_size,temp; + + mt6628_RampDown(); + mt6628_read(FM_MAIN_CTRL, &temp); + mt6628_Mute(fm_true); + + if (FM_LOCK(cmd_buf_lock)) return fm_false; + pkt_size = mt6628_seek(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6628_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + *pFreq = res->seek_result; + //fm_cb_op->cur_freq_set(*pFreq); + } else { + WCN_DBG(FM_ALT | CHIP, "mt6628_seek failed\n"); + return ret; + } + + //get the result freq + WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq); + mt6628_RampDown(); + if((temp&0x0020) == 0) + { + mt6628_Mute(fm_false); + } + + return fm_true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static fm_s32 mt6628_full_cqi_get(fm_s32 min_freq, fm_s32 max_freq, fm_s32 space, fm_s32 cnt) +{ + fm_s32 ret = 0; + fm_u16 pkt_size; + fm_u16 freq, orig_freq; + fm_s32 i, j, k; + fm_s32 space_val, max, min, num; + struct mt6628_full_cqi *p_cqi; + fm_u8 *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + fm_u8 cqi_log_buf[100] = {0}; + fm_s32 pos; + fm_u8 cqi_log_path[100] = {0}; + + WCN_DBG(FM_NTC | CHIP, "6628 cqi log start\n"); + // for soft-mute tune, and get cqi + freq = fm_cb_op->cur_freq_get(); + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + // get cqi + orig_freq = freq; + if (0 == fm_get_channel_space(min_freq)) { + min = min_freq * 10; + } else { + min = min_freq; + } + if (0 == fm_get_channel_space(max_freq)) { + max = max_freq * 10; + } else { + max = max_freq; + } + if (space == 0x0001) { + space_val = 5; // 50Khz + } else if (space == 0x0002) { + space_val = 10; // 100Khz + } else if (space == 0x0004) { + space_val = 20; // 200Khz + } else { + space_val = 10; + } + num = (max - min) / space_val + 1; //Eg, (8760 - 8750) / 10 + 1 = 2 + for (k = 0; (10000 == orig_freq) && (0xffffffff == g_dbg_level) && (k < cnt); k++) + { + WCN_DBG(FM_NTC | CHIP, "cqi file:%d\n", k+1); + freq = min; + pos = 0; + fm_memcpy(cqi_log_path, FM_CQI_LOG_PATH, strlen(FM_CQI_LOG_PATH)); + sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k+1); + fm_file_write(cqi_log_path, cqi_log_title, strlen(cqi_log_title), &pos); + for (j = 0; j < num; j++) + { + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]); + p_cqi = (struct mt6628_full_cqi*)&res->cqi[2]; + for (i = 0; i < res->cqi[1]; i++) { + // just for debug + WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + p_cqi[i].ch, + p_cqi[i].rssi, + p_cqi[i].pamd, + p_cqi[i].pr, + p_cqi[i].fpamd, + p_cqi[i].mr, + p_cqi[i].atdc, + p_cqi[i].prx, + p_cqi[i].atdev, + p_cqi[i].smg, + p_cqi[i].drssi); + // format to buffer + sprintf(cqi_log_buf, "%04d,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,\n", + p_cqi[i].ch, + p_cqi[i].rssi, + p_cqi[i].pamd, + p_cqi[i].pr, + p_cqi[i].fpamd, + p_cqi[i].mr, + p_cqi[i].atdc, + p_cqi[i].prx, + p_cqi[i].atdev, + p_cqi[i].smg, + p_cqi[i].drssi); + // write back to log file + fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos); + } + } + else + { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + ret = -1; + } + freq += space_val; + } + fm_cb_op->cur_freq_set(0);//avoid run too much times + } + WCN_DBG(FM_NTC | CHIP, "6628 cqi log done\n"); + + return ret; +} + + +static fm_bool mt6628_Scan(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL, + fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space) +{ + fm_s32 ret = 0; + fm_u16 pkt_size,temp; + fm_u16 offset = 0; + fm_u16 tmp_scanTBLsize = *ScanTBLsize; + + if ((!pScanTBL) || (tmp_scanTBLsize == 0)) { + WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n"); + return fm_false; + } + + WCN_DBG(FM_NTC | CHIP, "start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space); + + mt6628_RampDown(); + mt6628_read(FM_MAIN_CTRL, &temp); + mt6628_Mute(fm_true); + + mt6628_full_cqi_get(min_freq, max_freq, space, 5); + + // normal scan + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_scan(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_SCAN_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE); + WCN_DBG(FM_NTC | CHIP, "Rx scan result:\n"); + + for (offset = 0; offset < tmp_scanTBLsize; offset++) { + WCN_DBG(FM_NTC | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset)); + } + + *ScanTBLsize = tmp_scanTBLsize; + } else { + WCN_DBG(FM_ALT | CHIP, "mt6628_scan failed\n"); + return ret; + } + + mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0 + if((temp&0x0020) == 0) + { + mt6628_Mute(fm_false); + } + + return fm_true; +} + +//add for scan cancel case +static fm_bool cqi_abort = fm_false; + +static fm_s32 mt6628_CQI_Get(fm_s8 *buf, fm_s32 buf_len) +{ + fm_s32 ret = 0; + fm_s32 i; + fm_u16 pkt_size; + struct mt6628_fm_cqi *pmt6628_cqi; + struct adapt_fm_cqi *pcqi; + + if (!buf || buf_len < FM_CQI_BUF_SIZE) { + return -FM_EBUF; + } + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_cqi_get(cmd_buf, TX_BUF_SIZE); + if (cqi_abort == fm_true) { + cqi_abort = fm_false; + ret = -1; + } else { + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_CQI_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result); + } + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) { + //FIXEDME + pmt6628_cqi = (struct mt6628_fm_cqi*)res->cqi; + pcqi = (struct adapt_fm_cqi*)buf; + + for (i = 0; i < (sizeof(res->cqi) / sizeof(struct mt6628_fm_cqi)); i++) { + pcqi[i].ch = (pmt6628_cqi[i].ch * 10 / 2) + 6400; + pcqi[i].rssi = (fm_s32)pmt6628_cqi[i].rssi; + + if (pcqi[i].rssi >= 32768) { + pcqi[i].rssi = pcqi[i].rssi - 65536; + } + + pcqi[i].rssi = ((pcqi[i].rssi * 6) >> 4); + WCN_DBG(FM_NTC | CHIP, "%d --> %d(dbm)\n", pcqi[i].ch, pcqi[i].rssi); + } + } else { + WCN_DBG(FM_ALT | CHIP, "mt6628 get CQI failed:%d\n",ret); + } + + mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0 + + return ret; +} + +static fm_bool scan_abort = fm_false; + +#ifdef MTK_FM_50KHZ_SUPPORT +#define SCAN_SEG_LEN 250 +static fm_s8 raw_buf[16 * sizeof(struct adapt_fm_cqi)] = {0}; + +static fm_bool mt6628_Scan_50KHz(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL, + fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space) +{ + fm_s32 ret = 0; + fm_s32 num; + fm_s32 seg; + fm_s32 i, j; + fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip + fm_s32 start_freq, end_freq; + fm_s32 ch_offset, step, tmp_val; + fm_s32 chl_cnt = 0; + fm_s32 word_offset, bit_offset; + fm_s32 space_val = 5; + struct adapt_fm_cqi *pCQI = (struct adapt_fm_cqi *)raw_buf; + + if (space == 0x0001) { + space_val = 5; // 50Khz + } else if (space == 0x0002) { + space_val = 10; // 100Khz + } else if (space == 0x0004) { + space_val = 20; // 200Khz + } + + // calculate segment number + num = (max_freq - min_freq) / space_val; //Eg, (10800 - 8750) / 5 = 410 + seg = (num / SCAN_SEG_LEN) + ((num % SCAN_SEG_LEN) ? 1 : 0); //Eg, (410 / 200) + ((410 % 200) ? 1 : 0) = 2 + 1 = 3 + + FM_FIFO_RESET(cqi_fifo); + fm_memset(pScanTBL, 0, sizeof(fm_u16) * (*ScanTBLsize)); + + // do scan + scan_abort = fm_false; // reset scan cancel flag + for (i = 0; i < seg; i++) { + start_freq = min_freq + SCAN_SEG_LEN * space_val * i; + end_freq = min_freq + SCAN_SEG_LEN * space_val * (i + 1) - space_val; + end_freq = (end_freq > max_freq) ? max_freq : end_freq; + chl_cnt = 0; + + if (fm_true == scan_abort) { + scan_abort = fm_false; + return fm_false; + } + + if (fm_false == mt6628_Scan(start_freq, end_freq, pFreq, scan_tbl, ScanTBLsize, scandir, space)) { + return fm_false; + } + + // get channel count + for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) { + if (scan_tbl[ch_offset] == 0) + continue; + for (step = 0; step < 16; step++) { + if (scan_tbl[ch_offset] & (1 << step)) { + tmp_val = start_freq + (ch_offset * 16 + step) * space_val; + WCN_DBG(FM_NTC | CHIP, "freq %d, end freq %d\n", tmp_val, end_freq); + if (tmp_val <= end_freq) { + chl_cnt++; + // set reult bitmap + word_offset = (tmp_val - min_freq) / space_val / 16; + bit_offset = (tmp_val - min_freq) / space_val % 16; + if ((word_offset < 26) && (word_offset >= 0)) { + pScanTBL[word_offset] |= (1 << bit_offset); + } + WCN_DBG(FM_NTC | CHIP, "cnt %d, word %d, bit %d\n", chl_cnt, word_offset, bit_offset); + } + } + } + } + + // get cqi info + while (chl_cnt > 0) { + ret = mt6628_CQI_Get(raw_buf, 16 * sizeof(struct adapt_fm_cqi)); + if (ret) { + return ret; + } + + // add valid channel to cqi_fifo + for (j = 0; j < sizeof(raw_buf) / sizeof(struct adapt_fm_cqi); j++) { + if ((pCQI[j].ch >= start_freq) && (pCQI[j].ch <= end_freq)) { + FM_FIFO_INPUT(cqi_fifo, pCQI + j); + WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) add to fifo\n", pCQI[j].ch, pCQI[j].rssi); + } + } + + chl_cnt -= 16; + } + } + + return fm_true; +} + + +static fm_s32 mt6628_CQI_Get_50KHz(fm_s8 *buf, fm_s32 buf_len) +{ + fm_s32 ret = 0; + fm_s32 i; + struct adapt_fm_cqi tmp = { + .ch = 0, + .rssi = 0, + }; + struct adapt_fm_cqi *pcqi = (struct adapt_fm_cqi *)buf; + + + if (!buf || buf_len < FM_CQI_BUF_SIZE) { + return -FM_EBUF; + } + + for (i = 0; ((i < (buf_len / sizeof(struct adapt_fm_cqi))) && \ + (fm_false == FM_FIFO_IS_EMPTY(cqi_fifo))); i++) { + FM_FIFO_OUTPUT(cqi_fifo, &tmp); + pcqi[i].ch = tmp.ch; + pcqi[i].rssi = tmp.rssi; + WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) get from fifo\n", pcqi[i].ch, pcqi[i].rssi); + } + + return ret; +} + +#endif //MTK_FM_50KHZ_SUPPORT + + +/* + * mt6628_GetCurRSSI - get current freq's RSSI value + * RS=RSSI + * If RS>511, then RSSI(dBm)= (RS-1024)/16*6 + * else RSSI(dBm)= RS/16*6 + */ +static fm_s32 mt6628_GetCurRSSI(fm_s32 *pRSSI) +{ + fm_u16 tmp_reg; + + mt6628_read(FM_RSSI_IND, &tmp_reg); + tmp_reg = tmp_reg & 0x03ff; + + if (pRSSI) { + *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4); + WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI); + } else { + WCN_DBG(FM_ERR | CHIP, "get rssi para error\n"); + return -FM_EPARA; + } + + return 0; +} + +static fm_u16 mt6628_vol_tbl[16] = { \ + 0x0000, 0x0519, 0x066A, 0x0814, \ + 0x0A2B, 0x0CCD, 0x101D, 0x1449, \ + 0x198A, 0x2027, 0x287A, 0x32F5, \ + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; +static fm_s32 mt6628_SetVol(fm_u8 vol) +{ + fm_s32 ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = mt6628_write(0x7D, mt6628_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } else { + WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", vol); + } + + if (vol == 10) { + fm_print_cmd_fifo(); //just for debug + fm_print_evt_fifo(); + } + return 0; +} + +static fm_s32 mt6628_GetVol(fm_u8 *pVol) +{ + int ret = 0; + fm_u16 tmp; + fm_s32 i; + + FMR_ASSERT(pVol); + + ret = mt6628_read(0x7D, &tmp); + if (ret) { + *pVol = 0; + WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n"); + return ret; + } + + for (i = 0; i < 16; i++) { + if (mt6628_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static fm_s32 mt6628_dump_reg(void) +{ + fm_s32 i; + fm_u16 TmpReg; + for(i=0; i<0xff; i++) + { + mt6628_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg); + } + return 0; +} + +static fm_bool mt6628_GetMonoStereo(fm_u16 *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + fm_u16 TmpReg; + + if (pMonoStereo) { + mt6628_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return fm_false; + } + + WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo); + return fm_true; +} + +static fm_s32 mt6628_SetMonoStereo(fm_s32 MonoStereo) +{ + fm_s32 ret = 0; +#define FM_FORCE_MS 0x0008 + + WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + + mt6628_write(0x60, 0x3007); + + if (MonoStereo) { + ret = mt6628_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS); + } else { + ret = mt6628_set_bits(0x75, 0x0000, ~FM_FORCE_MS); + } + + return ret; +} + +static fm_s32 mt6628_GetCapArray(fm_s32 *ca) +{ + fm_u16 dataRead; + fm_u16 tmp = 0; + + FMR_ASSERT(ca); + mt6628_read(0x60, &tmp); + mt6628_write(0x60, tmp&0xFFF7); //0x60 D3=0 + + mt6628_read(0x26, &dataRead); + *ca = dataRead; + + mt6628_write(0x60, tmp); //0x60 D3=1 + return 0; +} + +/* + * mt6628_GetCurPamd - get current freq's PAMD value + * PA=PAMD + * If PA>511 then PAMD(dB)= (PA-1024)/16*6, + * else PAMD(dB)=PA/16*6 + */ +static fm_bool mt6628_GetCurPamd(fm_u16 *pPamdLevl) +{ + fm_u16 tmp_reg; + fm_u16 dBvalue,valid_cnt=0; + int i,total=0; + for (i = 0; i < 8; i++) + { + if (mt6628_read(FM_ADDR_PAMD, &tmp_reg)) + { + *pPamdLevl = 0; + return fm_false; + } + + tmp_reg &= 0x03FF; + dBvalue = (tmp_reg > 256) ? ((512 - tmp_reg) * 6 / 16) : 0; + if(dBvalue != 0) + { + total += dBvalue; + valid_cnt++; + WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue); + } + Delayms(3); + } + if(valid_cnt != 0) + { + *pPamdLevl = total/valid_cnt; + } + else + { + *pPamdLevl = 0; + } + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return fm_true; +} + +static fm_s32 mt6628_ScanStop(void) +{ + cqi_abort = fm_true; + scan_abort = fm_true; + fm_force_active_event(FLAG_SCAN_DONE | FLAG_CQI_DONE); + + return 0; +} + +static fm_s32 mt6628_SeekStop(void) +{ + return fm_force_active_event(FLAG_SEEK_DONE); +} + + +/* + * mt6628_I2s_Setting - set the I2S state on MT6628 + * @onoff - I2S on/off + * @mode - I2S mode: Master or Slave + * + * Return:0, if success; error code, if failed + */ +static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample) +{ + fm_u16 tmp_state = 0; + fm_u16 tmp_mode = 0; + fm_u16 tmp_sample = 0; + fm_s32 ret = 0; + + if (onoff == MT6628_I2S_ON) { + tmp_state = 0x0080; //I2S Frequency tracking on, 0x61 D7=1 + mt6628_i2s_inf.status = 1; + } else if (onoff == MT6628_I2S_OFF) { + tmp_state = 0x0000; //I2S Frequency tracking off, 0x61 D7=0 + mt6628_i2s_inf.status = 0; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff); + ret = -FM_EPARA; + goto out; + } + + if (mode == MT6628_I2S_MASTER) { + tmp_mode = 0x0000; //6620 as I2S master, set 0x9B D3=0 + mt6628_i2s_inf.mode = 1; + } else if (mode == MT6628_I2S_SLAVE) { + tmp_mode = 0x0008; //6620 as I2S slave, set 0x9B D3=1 + mt6628_i2s_inf.mode = 0; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode); + ret = -FM_EPARA; + goto out; + } + + if (sample == MT6628_I2S_32K) { + tmp_sample = 0x0000; //6620 I2S 32KHz sample rate, 0x5F D11~12 + mt6628_i2s_inf.rate = 32000; + } else if (sample == MT6628_I2S_44K) { + tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate + mt6628_i2s_inf.rate = 44100; + } else if (sample == MT6628_I2S_48K) { + tmp_sample = 0x1000; //6620 I2S 48KHz sample rate + mt6628_i2s_inf.rate = 48000; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample); + ret = -FM_EPARA; + goto out; + } + + if ((ret = mt6628_set_bits(0x5F, tmp_sample, 0xE7FF))) + goto out; + + if ((ret = mt6628_set_bits(0x9B, tmp_mode, 0xFFF7))) + goto out; + + if ((ret = mt6628_set_bits(0x61, tmp_state, 0xFF7F))) + goto out; + + WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n", + (onoff == MT6628_I2S_ON) ? "On" : "Off", + (mode == MT6628_I2S_MASTER) ? "Master" : "Slave", + sample); +out: + return ret; +} + + + +static fm_s32 mt6628_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample) +{ + FMR_ASSERT(ponoff); + FMR_ASSERT(pmode); + FMR_ASSERT(psample); + + *ponoff = mt6628_i2s_inf.status; + *pmode = mt6628_i2s_inf.mode; + *psample = mt6628_i2s_inf.rate; + + return 0; +} + + +static fm_s32 mt6628_hw_info_get(struct fm_hw_info *req) +{ + FMR_ASSERT(req); + + req->chip_id = mt6628_hw_info.chip_id; + req->eco_ver = mt6628_hw_info.eco_ver; + req->patch_ver = mt6628_hw_info.patch_ver; + req->rom_ver = mt6628_hw_info.rom_ver; + + return 0; +} + +static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid) +{ + fm_s32 ret=0; + fm_u16 pkt_size; + //fm_u16 freq;//, orig_freq; + struct mt6628_full_cqi *p_cqi; + fm_s32 RSSI=0, PAMD=0,MR=0, ATDC=0; + fm_u32 PRX=0,ATDEV=0; + fm_u16 softmuteGainLvl=0; + + if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK); + pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && res) + { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]); + p_cqi = (struct mt6628_full_cqi*)&res->cqi[2]; + // just for debug + WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + p_cqi->ch, + p_cqi->rssi, + p_cqi->pamd, + p_cqi->pr, + p_cqi->fpamd, + p_cqi->mr, + p_cqi->atdc, + p_cqi->prx, + p_cqi->atdev, + p_cqi->smg, + p_cqi->drssi); + RSSI = ((p_cqi->rssi & 0x03FF) >= 512) ? ((p_cqi->rssi & 0x03FF) - 1024) : (p_cqi->rssi & 0x03FF); + PAMD = ((p_cqi->pamd & 0x1FF) >= 256) ? ((p_cqi->pamd & 0x01FF) - 512) : (p_cqi->pamd & 0x01FF); + MR = ((p_cqi->mr & 0x01FF) >= 256) ? ((p_cqi->mr & 0x01FF) - 512) : (p_cqi->mr & 0x01FF); + ATDC =(p_cqi->atdc >= 32768) ? (65536 - p_cqi->atdc) : (p_cqi->atdc); + if(ATDC < 0) + { + ATDC = (~(ATDC)) - 1;//Get abs value of ATDC + } + PRX = (p_cqi->prx & 0x00FF); + ATDEV = p_cqi->atdev; + softmuteGainLvl = p_cqi->smg; + //check if the channel is valid according to each CQIs + if((RSSI >= mt6628_fm_config.rx_cfg.long_ana_rssi_th) + && (PAMD <= mt6628_fm_config.rx_cfg.pamd_th) + && (ATDC <= mt6628_fm_config.rx_cfg.atdc_th) + && (MR >= mt6628_fm_config.rx_cfg.mr_th) + && (PRX >= mt6628_fm_config.rx_cfg.prx_th) + && (ATDEV >= mt6628_fm_config.rx_cfg.atdev_th) + && (softmuteGainLvl >= mt6628_fm_config.rx_cfg.smg_th)) + { + *valid = fm_true; + } + else + { + *valid = fm_false; + } + *rssi = RSSI; +/* if(RSSI < -296) + WCN_DBG(FM_NTC | CHIP, "rssi\n"); + else if(PAMD > -12) + WCN_DBG(FM_NTC | CHIP, "PAMD\n"); + else if(ATDC > 3496) + WCN_DBG(FM_NTC | CHIP, "ATDC\n"); + else if(MR < -67) + WCN_DBG(FM_NTC | CHIP, "MR\n"); + else if(PRX < 80) + WCN_DBG(FM_NTC | CHIP, "PRX\n"); + else if(ATDEV < ATDC) + WCN_DBG(FM_NTC | CHIP, "ATDEV\n"); + else if(softmuteGainLvl < 16421) + WCN_DBG(FM_NTC | CHIP, "softmuteGainLvl\n"); + */ + } + else + { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return fm_false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid); + return fm_true; +} + +static fm_bool mt6628_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value) +{ + return fm_true; +} + +static fm_s32 MT6628fm_low_power_wa_default(fm_s32 fmon) +{ + return 0; +} + +fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + //Basic functions. + + FMR_ASSERT(ops); + FMR_ASSERT(ops->cb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb_op = &ops->cb; + + ops->bi.low_pwr_wa = MT6628fm_low_power_wa_default; + ops->bi.pwron = mt6628_pwron; + ops->bi.pwroff = mt6628_pwroff; + ops->bi.msdelay = Delayms; + ops->bi.usdelay = Delayus; + ops->bi.read = mt6628_read; + ops->bi.write = mt6628_write; + ops->bi.setbits = mt6628_set_bits; + ops->bi.chipid_get = mt6628_get_chipid; + ops->bi.mute = mt6628_Mute; + ops->bi.rampdown = mt6628_RampDown; + ops->bi.pwrupseq = mt6628_PowerUp; + ops->bi.pwrdownseq = mt6628_PowerDown; + ops->bi.setfreq = mt6628_SetFreq; + ops->bi.seek = mt6628_Seek; + ops->bi.seekstop = mt6628_SeekStop; + ops->bi.scan = mt6628_Scan; + ops->bi.cqi_get = mt6628_CQI_Get; + #ifdef MTK_FM_50KHZ_SUPPORT + ops->bi.scan = mt6628_Scan_50KHz; + ops->bi.cqi_get = mt6628_CQI_Get_50KHz; + #endif + ops->bi.scanstop = mt6628_ScanStop; + ops->bi.rssiget = mt6628_GetCurRSSI; + ops->bi.volset = mt6628_SetVol; + ops->bi.volget = mt6628_GetVol; + ops->bi.dumpreg = mt6628_dump_reg; + ops->bi.msget = mt6628_GetMonoStereo; + ops->bi.msset = mt6628_SetMonoStereo; + ops->bi.pamdget = mt6628_GetCurPamd; + ops->bi.em = mt6628_em_test; + ops->bi.anaswitch = mt6628_SetAntennaType; + ops->bi.anaget = mt6628_GetAntennaType; + ops->bi.caparray_get = mt6628_GetCapArray; + ops->bi.i2s_set = mt6628_I2s_Setting; + ops->bi.hwinfo_get = mt6628_hw_info_get; + ops->bi.i2s_get = mt6628_i2s_info_get; + ops->bi.is_dese_chan = mt6628_is_dese_chan; + ops->bi.softmute_tune = mt6628_soft_mute_tune; + ops->bi.desense_check = mt6628_desense_check; + ops->bi.cqi_log = mt6628_full_cqi_get; + + cmd_buf_lock = fm_lock_create("28_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6628 fm lib alloc tx buf failed\n"); + ret = -1; + } + +#ifdef MTK_FM_50KHZ_SUPPORT + cqi_fifo = fm_fifo_create("6628_cqi_fifo", sizeof(struct adapt_fm_cqi), 640); + if (!cqi_fifo) { + WCN_DBG(FM_ALT | CHIP, "6628 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + //Basic functions. + FMR_ASSERT(ops); + +#ifdef MTK_FM_50KHZ_SUPPORT + fm_fifo_release(cqi_fifo); +#endif + + if (cmd_buf) { + fm_free(cmd_buf); + cmd_buf = NULL; + } + + ret = fm_lock_put(cmd_buf_lock); + fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface)); + return ret; +} +//static struct fm_pub pub; +//static struct fm_pub_cb *pub_cb = &pub.pub_tbl; + +static const fm_u16 mt6628_mcu_dese_list[] = { + 7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410 +}; + +static const fm_u16 mt6628_gps_dese_list[] = { + 7850, 7860 +}; + +static const fm_s8 mt6628_chan_para_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, //7600~7695 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7700~7795 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7800~7895 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7900~7995 + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8000~8095 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8100~8195 + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8200~8295 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8300~8395 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, //8400~8495 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8500~8595 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8600~8695 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8700~8795 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8800~8895 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8900~8995 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9000~9095 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9100~9195 + 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9200~9295 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9300~9395 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, //9400~9495 + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, //9500~9595 + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9600~9695 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9700~9795 + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9800~9895 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, //9900~9995 + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10000~10095 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10100~10195 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, //10200~10295 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10300~10395 + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10400~10495 + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10500~10595 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10600~10695 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, //10700~10795 + 0 //10800 +}; + + +static const fm_u16 mt6628_scan_dese_list[] = { + 7680, 8210, 8450, 9210, 9220, 9600, 9840, 10400, 10750, 10760 +}; + +// return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no +static fm_s32 mt6628_is_dese_chan(fm_u16 freq) +{ + fm_s32 size; + + size = sizeof(mt6628_scan_dese_list) / sizeof(mt6628_scan_dese_list[0]); + + if (0 == fm_get_channel_space(freq)) { + freq *= 10; + } + + while (size) { + if (mt6628_scan_dese_list[size -1] == freq) + return 1; + + size--; + } + + return 0; +} + +/* return value: +1, is desense channel and rssi is less than threshold; +0, not desense channel or it is but rssi is more than threshold.*/ +static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi) +{ + if(mt6628_is_dese_chan(freq)) + { + if(rssi (size - 1)) ? (size - 1) : pos; + + return mt6628_chan_para_map[pos]; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c new file mode 100755 index 000000000000..b62c89b0d99b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c @@ -0,0 +1,471 @@ +/* mt6628_fm_link.c + * + * (C) Copyright 2009 + * MediaTek + * Hongcheng + * + * MT6628 FM Radio Driver -- setup data link + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #if 0 +#include +#include + +#include "stp_exp.h" +#include "wmt_exp.h" + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +#include "mt6628_fm.h" +#include "mt6628_fm_link.h" + +static struct fm_link_event *link_event; + +static struct fm_trace_fifo_t *cmd_fifo; + +static struct fm_trace_fifo_t *evt_fifo; + +static fm_s32 (*reset)(fm_s32 sta) = NULL; + +static void mt6628_fm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, + ENUM_WMTMSG_TYPE_T type, + void *buf, + unsigned int sz) +{ + //To handle reset procedure please + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((char *)&rst_msg, (char *)buf, sz); + WCN_DBG(FM_WAR | LINK, "[src=%d], [dst=%d], [type=%d], [buf=0x%x], [sz=%d], [max=%d]\n", src, dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_FM) && (type == WMTMSG_TYPE_RESET)) { + if (rst_msg == WMTRSTMSG_RESET_START) { + WCN_DBG(FM_WAR | LINK, "FM restart start!\n"); + if (reset) { + reset(1); + } + + } else if (rst_msg == WMTRSTMSG_RESET_END) { + WCN_DBG(FM_WAR | LINK, "FM restart end!\n"); + if (reset) { + reset(0); + } + } + } + } else { + /*message format invalid*/ + WCN_DBG(FM_WAR | LINK, "message format invalid!\n"); + } +} + + +fm_s32 fm_link_setup(void* data) +{ + fm_s32 ret = 0; + + if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) { + WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n"); + return -1; + } + + link_event->ln_event = fm_flag_event_create("ln_evt"); + + if (!link_event->ln_event) { + WCN_DBG(FM_ALT | LINK, "create mt6628_ln_event failed\n"); + fm_free(link_event); + return -1; + } + + fm_flag_event_get(link_event->ln_event); + + + WCN_DBG(FM_NTC | LINK, "fm link setup\n"); + + cmd_fifo = fm_trace_fifo_create("cmd_fifo"); + if (!cmd_fifo) { + WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n"); + ret = -1; + goto failed; + } + + evt_fifo = fm_trace_fifo_create("evt_fifo"); + if (!evt_fifo) { + WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n"); + ret = -1; + goto failed; + } + + reset = data; // get whole chip reset cb + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, mt6628_fm_wholechip_rst_cb); + return 0; + +failed: + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + return ret; +} + +fm_s32 fm_link_release(void) +{ + + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + fm_flag_event_put(link_event->ln_event); + if (link_event) { + fm_free(link_event); + } + + WCN_DBG(FM_NTC | LINK, "fm link release\n"); + return 0; +} + +/* + * fm_ctrl_rx + * the low level func to read a rigister + * @addr - rigister address + * @val - the pointer of target buf + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val) +{ + return 0; +} + +/* + * fm_ctrl_tx + * the low level func to write a rigister + * @addr - rigister address + * @val - value will be writed in the rigister + * If success, return 0; else error code + */ +fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val) +{ + return 0; +} + +/* + * fm_cmd_tx() - send cmd to FM firmware and wait event + * @buf - send buffer + * @len - the length of cmd + * @mask - the event flag mask + * @ cnt - the retry conter + * @timeout - timeout per cmd + * Return 0, if success; error code, if failed + */ +fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result)) +{ + fm_s32 ret_time = 0; + struct task_struct *task = current; + struct fm_trace_t trace; + + if ((NULL == buf) || (len < 0) || (0 == mask) + || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) { + WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n"); + return -FM_EPARA; + } + + FM_EVENT_CLR(link_event->ln_event, mask); + +#ifdef FM_TRACE_ENABLE + trace.type = buf[0]; + trace.opcode = buf[1]; + trace.len = len - 4; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len); +#endif + +sw_retry: + +#ifdef FM_TRACE_ENABLE + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + + //send cmd to FM firmware + if (mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX) == 0) { + WCN_DBG(FM_EMG | LINK, "send data over stp failed\n"); + return -FM_ELINK; + } + + //wait the response form FM firmware + ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout); + + if (!ret_time) { + if (0 < cnt--) { + WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid); + fm_print_cmd_fifo(); + fm_print_evt_fifo(); + return -FM_EFW; + goto sw_retry; //retry if timeout and retry cnt > 0 + } else { + WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n"); + return -FM_EFW; + } + } + + FM_EVENT_CLR(link_event->ln_event, mask); + + if (callback) { + callback(&link_event->result); + } + + return 0; +} + +fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32)) +{ + fm_s32 len; + fm_s32 i = 0; + fm_u8 opcode = 0; + fm_u16 length = 0; + fm_u8 ch; + fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps + static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE; + struct fm_trace_t trace; + struct task_struct *task = current; + + len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX); + WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]); + + while (i < len) { + ch = rx_buf[i]; + + switch (state) { + case FM_TASK_RX_PARSER_PKT_TYPE: + + if (ch == FM_TASK_EVENT_PKT_TYPE) { + if ((i + 5) < RX_BUF_SIZE) { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]); + } else { + WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]); + } + + state = FM_TASK_RX_PARSER_OPCODE; + } else { + WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch); + } + + i++; + break; + + case FM_TASK_RX_PARSER_OPCODE: + i++; + opcode = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_1; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_1: + i++; + length = ch; + state = FM_TASK_RX_PARSER_PKT_LEN_2; + break; + + case FM_TASK_RX_PARSER_PKT_LEN_2: + i++; + length |= (fm_u16)(ch << 0x8); + +#ifdef FM_TRACE_ENABLE + trace.type = FM_TASK_EVENT_PKT_TYPE; + trace.opcode = opcode; + trace.len = length; + trace.tid = (fm_s32)task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length); + + if (fm_true == FM_TRACE_FULL(cmd_fifo)) { + FM_TRACE_OUT(cmd_fifo, NULL); + } + FM_TRACE_IN(cmd_fifo, &trace); +#endif + if (length > 0) { + state = FM_TASK_RX_PARSER_PKT_PAYLOAD; + } else { + state = FM_TASK_RX_PARSER_PKT_TYPE; + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + } + + break; + + case FM_TASK_RX_PARSER_PKT_PAYLOAD: + + switch (opcode) { + case FM_TUNE_OPCODE: + + if ((length == 1) && (rx_buf[i] == 1)) { + FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE); + } + + break; + + case FM_SOFT_MUTE_TUNE_OPCODE: + + if (length >= 2) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length); + FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE); + } + break; + + case FM_SEEK_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz + } + + FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE); + break; + + case FM_SCAN_OPCODE: + + //check if the result data is long enough + if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) { + WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + return 0; + } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) { + fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE); + } else { + fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE); + FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE); + } + + break; + + case FSPI_READ_OPCODE: + + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8)); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + case RDS_RX_DATA_OPCODE: + + //check if the rds data is long enough + if ((RX_BUF_SIZE - i) < length) { + WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + //copy rds data to rds buf + fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length); + + /*Handle the RDS data that we get*/ + if (rds_parser) { + rds_parser(&link_event->result.rds_rx_result, length); + } else { + WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n"); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + + default: + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + state = FM_TASK_RX_PARSER_PKT_TYPE; + i += length; + break; + + default: + break; + } + } + + return 0; +} + +fm_bool fm_wait_stc_done(fm_u32 sec) +{ + return fm_true; +} + +fm_s32 fm_force_active_event(fm_u32 mask) +{ + fm_u32 flag; + + flag = FM_EVENT_GET(link_event->ln_event); + WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag); + flag = FM_EVENT_SEND(link_event->ln_event, mask); + WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag); + + return 0; +} + + +extern fm_s32 fm_print_cmd_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(cmd_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "trace\n"); + } +#endif + + return 0; +} + +extern fm_s32 fm_print_evt_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + fm_s32 i = 0; + + while (fm_false == FM_TRACE_EMPTY(evt_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(evt_fifo, &trace); + WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time))); + i = 0; + while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) { + WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]); + i += 8; + } + WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name); + } +#endif + + return 0; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c new file mode 100755 index 000000000000..c16eabed8a85 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c @@ -0,0 +1,315 @@ +/* mt6628_rds.c + * + * (C) Copyright 2009 + * MediaTek + * hongcheng + * + * mt6628 FM Radio Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" +#include "mt6628_fm_reg.h" + + +static fm_bool bRDS_FirstIn = fm_false; +static fm_u32 gBLER_CHK_INTERVAL = 5000; +static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0; +static fm_u8 BAD_BLK_RATIO = 0; + +static struct fm_callback *fm_cb = NULL; +static struct fm_basic_interface *fm_bi = NULL; + + +static fm_bool mt6628_RDS_support(void); +static fm_s32 mt6628_RDS_enable(void); +static fm_s32 mt6628_RDS_disable(void); +static fm_u16 mt6628_RDS_Get_GoodBlock_Counter(void); +static fm_u16 mt6628_RDS_Get_BadBlock_Counter(void); +static fm_u8 mt6628_RDS_Get_BadBlock_Ratio(void); +static fm_u32 mt6628_RDS_Get_BlerCheck_Interval(void); +// static void mt6628_RDS_GetData(fm_u16 *data, fm_u16 datalen); +static void mt6628_RDS_Init_Data(rds_t *pstRDSData); + + + +static fm_bool mt6628_RDS_support(void) +{ + return fm_true; +} + +static fm_s32 mt6628_RDS_enable(void) +{ + fm_s32 ret = 0; + fm_u16 dataRead; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + ret = fm_bi->read(FM_RDS_CFG0, &dataRead); + ret = fm_bi->write(FM_RDS_CFG0, 6); //set buf_start_th + ret = fm_bi->read(FM_MAIN_CTRL, &dataRead); + ret = fm_bi->write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + + return ret; +} + +static fm_s32 mt6628_RDS_disable(void) +{ + fm_s32 ret = 0; + fm_u16 dataRead; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_bi->read(FM_MAIN_CTRL, &dataRead); + ret = fm_bi->write(FM_MAIN_CTRL, dataRead&(~RDS_MASK)); + + return ret; +} + +static fm_u16 mt6628_RDS_Get_GoodBlock_Counter(void) +{ + fm_u16 tmp_reg; + + fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u16 mt6628_RDS_Get_BadBlock_Counter(void) +{ + fm_u16 tmp_reg; + + fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_u8 mt6628_RDS_Get_BadBlock_Ratio(void) +{ + fm_u16 tmp_reg; + fm_u16 gbc; + fm_u16 bbc; + + gbc = mt6628_RDS_Get_GoodBlock_Counter(); + bbc = mt6628_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) { + tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc)); + } else { + tmp_reg = 0; + } + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg); + + return tmp_reg; +} + +static fm_s32 mt6628_RDS_BlockCounter_Reset(void) +{ + mt6628_RDS_disable(); + mt6628_RDS_enable(); + + return 0; +} + +static fm_u32 mt6628_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static fm_s32 mt6628_RDS_BlerCheck(rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + fm_u16 tempData = 0; + + do { + fm_bi->read(FM_RDS_DATA_REG, &tempData); + fm_bi->read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6628_RDS_GetData(fm_u16 *data, fm_u16 datalen) +{ +#define RDS_GROUP_DIFF_OFS 0x007C +#define RDS_FIFO_DIFF 0x007F +#define RDS_CRC_BLK_ADJ 0x0020 +#define RDS_CRC_CORR_CNT 0x001E +#define RDS_CRC_INFO 0x0001 + + fm_u16 CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + fm_u16 temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_bi->read(FM_RDS_FIFO_STATUS0, &temp); + RDSDataCount = ((RDS_GROUP_DIFF_OFS & temp) << 2); + + if ((temp & RDS_FIFO_DIFF) >= 4) { + //block A data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 10; + CRC |= (temp & RDS_CRC_INFO) << 3; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 11); + fm_bi->read(FM_RDS_DATA_REG, &data[0]); + + //block B data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 9; + CRC |= (temp & RDS_CRC_INFO) << 2; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 7); + fm_bi->read(FM_RDS_DATA_REG, &data[1]); + + //block C data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 8; + CRC |= (temp & RDS_CRC_INFO) << 1; + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 3); + fm_bi->read(FM_RDS_DATA_REG, &data[2]); + + //block D data and info handling + fm_bi->read(FM_RDS_INFO, &temp); + RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 7; + CRC |= (temp & RDS_CRC_INFO); + FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) >> 1); + fm_bi->read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_bi->read(FM_RDS_PWDI, &data[6]); + fm_bi->read(FM_RDS_PWDQ, &data[7]); + + fm_bi->read(FM_RDS_POINTER, &OutputPofm_s32); + + //Go fm_s32o RDS recovery handler while RDS output pofm_s32 doesn't align to 4 in numeric + if (OutputPofm_s32 & 0x3) { + RDS_Recovery_Handler(); + } + + } else { + for (; i < 8; i++) + data[i] = 0; + } +} +#endif + +static void mt6628_RDS_Init_Data(rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0 , sizeof(rds_t)); + bRDS_FirstIn = fm_true; + + fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData)); + fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS)); + fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON)); +} + +fm_bool mt6628_RDS_OnOff(rds_t *dst, fm_bool bFlag) +{ + if (mt6628_RDS_support() == fm_false) { + WCN_DBG(FM_ALT | RDSC, "mt6628_RDS_OnOff failed, RDS not support\n"); + return fm_false; + } + + if (bFlag) { + mt6628_RDS_Init_Data(dst); + mt6628_RDS_enable(); + } else { + mt6628_RDS_disable(); + } + + return fm_true; +} + +DEFINE_RDSLOG(mt6628_rds_log); + +/* mt6628_RDS_Efm_s32_Handler - response FM RDS interrupt + * @fm - main data structure of FM driver + * This function first get RDS raw data, then call RDS spec parser + */ +static fm_s32 mt6628_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void)) +{ + mt6628_rds_log.log_in(&mt6628_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static fm_s32 mt6628_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len) +{ + return mt6628_rds_log.log_out(&mt6628_rds_log, dst, dst_len); +} + +static fm_s32 mt6628_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static fm_s32 mt6628_rds_gc_reset(rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +fm_s32 MT6628fm_rds_ops_register(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + FMR_ASSERT(ops->bi.write); + FMR_ASSERT(ops->bi.read); + FMR_ASSERT(ops->bi.setbits); + FMR_ASSERT(ops->bi.usdelay); + fm_bi = &ops->bi; + + FMR_ASSERT(ops->cb.cur_freq_get); + FMR_ASSERT(ops->cb.cur_freq_set); + fm_cb = &ops->cb; + + ops->ri.rds_blercheck = mt6628_RDS_BlerCheck; + ops->ri.rds_onoff = mt6628_RDS_OnOff; + ops->ri.rds_parser = mt6628_rds_parser; + ops->ri.rds_gbc_get = mt6628_RDS_Get_GoodBlock_Counter; + ops->ri.rds_bbc_get = mt6628_RDS_Get_BadBlock_Counter; + ops->ri.rds_bbr_get = mt6628_RDS_Get_BadBlock_Ratio; + ops->ri.rds_bc_reset = mt6628_RDS_BlockCounter_Reset; + ops->ri.rds_bci_get = mt6628_RDS_Get_BlerCheck_Interval; + ops->ri.rds_log_get = mt6628_rds_log_get; + ops->ri.rds_gc_get = mt6628_rds_gc_get; + ops->ri.rds_gc_reset = mt6628_rds_gc_reset; + return ret; +} + +fm_s32 MT6628fm_rds_ops_unregister(struct fm_lowlevel_ops *ops) +{ + fm_s32 ret = 0; + + FMR_ASSERT(ops); + + fm_bi = NULL; + fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} + diff --git a/drivers/mtk_wcn_combo/drv_fm/private/Makefile b/drivers/mtk_wcn_combo/drv_fm/private/Makefile new file mode 100755 index 000000000000..1a8e79608d78 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/private/Makefile @@ -0,0 +1,44 @@ +# Makefile generated by Mediatek + +# fm support +ifeq ($(MTK_FM_SUPPORT), yes) + +ifeq ($(CUSTOM_KERNEL_FM), mt6628) +PRIV_CHIP = mt6628 +PRIV_SRC_PATH = private/src/$(PRIV_CHIP) +PRIV_CONFIG = $(CONFIG_MTK_FM) + +ccflags-y := \ + -I$(src)/inc \ + -I$(src)/$(PRIV_SRC_PATH) \ + -I$(src)/../inc \ + -I$(src)/../cust/$(PRIV_CHIP) \ + -I$(src)/../../combo/common_mt6628/include \ + -I$(src)/../../combo/common_mt6628/linux/include + + +obj-$(PRIV_CONFIG) += mtk_fm_priv.o +mtk_fm_priv-objs := \ + src/$(PRIV_CHIP)/$(PRIV_CHIP)_fm_private.o +endif + +ifeq ($(CUSTOM_KERNEL_FM), mt6620) +PRIV_CHIP = mt6620 +PRIV_SRC_PATH = private/src/$(PRIV_CHIP) +PRIV_CONFIG = $(CONFIG_MTK_FM) + +ccflags-y := \ + -I$(src)/inc \ + -I$(src)/$(PRIV_SRC_PATH) \ + -I$(src)/../inc \ + -I$(src)/../cust/$(PRIV_CHIP) \ + -I$(src)/../../combo/common/include \ + -I$(src)/../../combo/common/linux/include + + +obj-$(PRIV_CONFIG) += mtk_fm_priv.o +mtk_fm_priv-objs := \ + src/$(PRIV_CHIP)/$(PRIV_CHIP)_fm_private.o +endif + +endif diff --git a/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h new file mode 100755 index 000000000000..abc68feda64c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h @@ -0,0 +1,101 @@ +#ifndef __FM_PRIV_LOG_H__ +#define __FM_PRIV_LOG_H__ +#if 0 +#include "fm_typedef.h" + +/******************DBG level ************************/ +#define D_BASE 4 +#define D_IOCTL (1 << (D_BASE+0)) +#define D_RX (1 << (D_BASE+1)) +#define D_TIMER (1 << (D_BASE+2)) +#define D_BLKC (1 << (D_BASE+3)) +#define D_G0 (1 << (D_BASE+4)) +#define D_G1 (1 << (D_BASE+5)) +#define D_G2 (1 << (D_BASE+6)) +#define D_G3 (1 << (D_BASE+7)) +#define D_G4 (1 << (D_BASE+8)) +#define D_G14 (1 << (D_BASE+9)) +#define D_RAW (1 << (D_BASE+10)) +#define D_RDS (1 << (D_BASE+11)) +#define D_INIT (1 << (D_BASE+12)) +#define D_MAIN (1 << (D_BASE+13)) +#define D_CMD (1 << (D_BASE+14)) +#define D_ALL 0xfffffff0 + +#define L0 0x00000000 // EMERG, system will crush +#define L1 0x00000001 // ALERT, need action in time +#define L2 0x00000002 // CRIT, important HW or SW operation failed +#define L3 0x00000003 // ERR, normal HW or SW ERR +#define L4 0x00000004 // WARNING, importan path or somewhere may occurs err +#define L5 0x00000005 // NOTICE, normal case +#define L6 0x00000006 // INFO, print info if need +#define L7 0x00000007 // DEBUG, for debug info + +#define FM_EMERG L0 +#define FM_ALERT L1 +#define FM_CRIT L2 +#define FM_ERR L3 +#define FM_WARNING L4 +#define FM_NOTICE L5 +#define FM_INFO L6 +#define FM_DEBUG L7 + +extern fm_u32 g_dbg_level; + +#define FM_LOG_DBG(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_DEBUG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_INF(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_INFO <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_NTC(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_NOTICE <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_WAR(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_WARNING <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_ERR(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_ERR <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_CRT(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_CRIT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_ALT(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_ALERT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) + +#define FM_LOG_EMG(flag, fmt, args...) \ + do{ \ + if(pub_cb->log && (FM_EMERG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \ + pub_cb->log("[" #flag "]" fmt, ## args); \ + } \ + } while(0) +#endif +#endif //__FM_PRIV_LOG_H__ \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h new file mode 100755 index 000000000000..245a0236f08a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h @@ -0,0 +1,93 @@ +#ifndef __FM_PRIVATE_H__ +#define __FM_PRIVATE_H__ + +#include "fm_typedef.h" + +typedef enum fm_priv_state { + UNINITED, + INITED +} fm_priv_state_t; + +typedef enum fm_adpll_state { + FM_ADPLL_ON, + FM_ADPLL_OFF +} fm_adpll_state_t; + +typedef enum fm_hl_dese { + FM_HL_DESE_LOW, + FM_HL_DESE_HIGH +} fm_hl_dese_t; + +typedef enum fm_adpll_clk { + FM_ADPLL_16M, + FM_ADPLL_15M +} fm_adpll_clk_t; + +typedef enum fm_mcu_desense { + FM_MCU_DESE_ENABLE, + FM_MCU_DESE_DISABLE +} fm_mcu_desense_t; + +typedef enum fm_gps_desense { + FM_GPS_DESE_ENABLE, + FM_GPS_DESE_DISABLE +} fm_gps_desense_t; + +//6620 +typedef struct MT6620fm_priv_cb { + //Basic functions. + int (*hl_side)(uint16_t freq, int *hl); + int (*adpll_freq_avoid)(uint16_t freq, int *freqavoid); + int (*mcu_freq_avoid)(uint16_t freq, int *freqavoid); + int (*tx_pwr_ctrl)(uint16_t freq, int *ctr); + int (*rtc_drift_ctrl)(uint16_t freq, int *ctr); + int (*tx_desense_wifi)(uint16_t freq, int *ctr); + int (*is_dese_chan)(fm_u16 freq); // check if this is a de-sense channel +}MT6620fm_priv_cb_t; + +typedef struct MT6620fm_priv{ + int state; + void *data; + MT6620fm_priv_cb_t priv_tbl; +}MT6620fm_priv_t; + +//6628 +typedef struct fm_priv_cb { + //De-sense functions. + fm_s32(*is_dese_chan)(fm_u16 freq); // check if this is a de-sense channel + fm_s32(*hl_dese)(fm_u16 freq, void *arg); // return value: 0, low side; 1, high side; else error no + fm_s32(*fa_dese)(fm_u16 freq, void *arg); // return value: 0, fa off; 1, fa on; else error no + fm_s32(*mcu_dese)(fm_u16 freq, void *arg); // return value: 0, mcu dese disable; 1, enable; else error no + fm_s32(*gps_dese)(fm_u16 freq, void *arg); // return value: 0,mcu dese disable; 1, enable; else error no + fm_u16(*chan_para_get)(fm_u16 freq); //get channel parameter, HL side/ FA / ATJ +} fm_priv_cb_t; + +typedef struct fm_priv { + fm_s32 state; + fm_priv_cb_t priv_tbl; + void *data; +} fm_priv_t; + +typedef struct fm_pub_cb { + //Basic functions. + fm_s32(*read)(fm_u8 addr, fm_u16 *val); + fm_s32(*write)(fm_u8 addr, fm_u16 val); + fm_s32(*setbits)(fm_u8 addr, fm_u16 bits, fm_u16 mask); + fm_s32(*rampdown)(void); + fm_s32(*msdelay)(fm_u32 val); + fm_s32(*usdelay)(fm_u32 val); + fm_s32(*log)(const fm_s8 *arg1, ...); +} fm_pub_cb_t; + +typedef struct fm_pub { + fm_s32 state; + void *data; + struct fm_pub_cb pub_tbl; +} fm_pub_t; + + +#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM)) +extern fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub); +extern fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub); +#endif +#endif //__FM_PRIVATE_H__ \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/drv_wlan/Makefile b/drivers/mtk_wcn_combo/drv_wlan/Makefile new file mode 100755 index 000000000000..5c4e9ee1db4f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/Makefile @@ -0,0 +1,6 @@ +#ifeq ($(MTK_WLAN_SUPPORT), yes) + obj-$(CONFIG_MTK_COMBO_WIFI) += mt6620/ +# obj-$(CONFIG_MTK_COMBO_WIFI) += mt6628/ +#endif + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile b/drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile new file mode 100755 index 000000000000..2968515154cd --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MTK_COMBO_WIFI) += wlan/ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile new file mode 100755 index 000000000000..1dc8a6237179 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile @@ -0,0 +1,142 @@ +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- + +#include $(MTK_PATH_BUILD)/Makefile +ccflags-y += -DLINUX -DMT6620 + +ifeq ($(MTK_WAPI_SUPPORT), yes) + ccflags-y += -DCFG_SUPPORT_WAPI=1 +else + ccflags-y += -DCFG_SUPPORT_WAPI=0 +endif + +ifeq ($(HAVE_XLOG_FEATURE), yes) + ccflags-y += -DCFG_SUPPORT_XLOG=1 +else + ccflags-y += -DCFG_SUPPORT_XLOG=0 +endif + +ifeq ($(HAVE_AEE_FEATURE), yes) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +#ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF_SDIO1), y) +# ccflags-y += -D_HIF_SDIO=1 +#endif + +MODULE_NAME := wlan_mt6620 + +ccflags-y += -D_HIF_SDIO=1 + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/sdio/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt + +obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-m += $(MODULE_NAME).o + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +HIF_DIR := os/linux/hif/sdio/ +NIC_DIR := nic/ +MGMT_DIR := mgmt/ + + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o + +OS_OBJS := $(OS_DIR)gl_init.o \ + $(OS_DIR)gl_kal.o \ + $(OS_DIR)gl_bow.o \ + $(OS_DIR)gl_wext.o \ + $(OS_DIR)gl_wext_priv.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)platform.o + +MGMT_OBJS := $(MGMT_DIR)ais_fsm.o \ + $(MGMT_DIR)aaa_fsm.o \ + $(MGMT_DIR)assoc.o \ + $(MGMT_DIR)auth.o \ + $(MGMT_DIR)bss.o \ + $(MGMT_DIR)cnm.o \ + $(MGMT_DIR)cnm_timer.o \ + $(MGMT_DIR)cnm_mem.o \ + $(MGMT_DIR)hem_mbox.o \ + $(MGMT_DIR)mib.o \ + $(MGMT_DIR)privacy.o \ + $(MGMT_DIR)rate.o \ + $(MGMT_DIR)rlm.o \ + $(MGMT_DIR)rlm_domain.o \ + $(MGMT_DIR)rlm_obss.o \ + $(MGMT_DIR)rlm_protection.o \ + $(MGMT_DIR)rsn.o \ + $(MGMT_DIR)saa_fsm.o \ + $(MGMT_DIR)scan.o \ + $(MGMT_DIR)scan_fsm.o \ + $(MGMT_DIR)sec_fsm.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +OS_OBJS += $(OS_DIR)gl_p2p.o \ + $(OS_DIR)gl_p2p_cfg80211.o \ + $(OS_DIR)gl_p2p_init.o \ + $(OS_DIR)gl_p2p_kal.o + +MGMT_OBJS += $(MGMT_DIR)p2p_assoc.o \ + $(MGMT_DIR)p2p_bss.o \ + $(MGMT_DIR)p2p_fsm.o \ + $(MGMT_DIR)p2p_func.o \ + $(MGMT_DIR)p2p_rlm.o \ + $(MGMT_DIR)p2p_rlm_obss.o \ + $(MGMT_DIR)p2p_scan.o \ + $(MGMT_DIR)p2p_ie.o \ + $(MGMT_DIR)p2p_state.o + + +ifeq ($(MTK_WAPI_SUPPORT), yes) +MGMT_OBJS += $(MGMT_DIR)wapi.o +endif + +ifeq ($(WLAN_PROC), y) +OS_OBJS += gl_proc.o +endif + +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)sdio.o + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c new file mode 100755 index 000000000000..95f2d7f25b76 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c @@ -0,0 +1,539 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/dump.c#1 $ +*/ + +/*! \file "dump.c" + \brief Provide memory dump function for debugging. + + Provide memory dump function for debugging. +*/ + + + +/* +** $Log: dump.c $ + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 19:58:51 GMT mtk01426 +** Init develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +dumpMemory8 ( + IN PUINT_8 pucStartAddr, + IN UINT_32 u4Length + ) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } + else { + switch (u4Length) { + case 1: + LOG_FUNC("(%08lx) %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0]); + break; + case 2: + LOG_FUNC("(%08lx) %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1]); + break; + case 3: + LOG_FUNC("(%08lx) %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2]); + break; + case 4: + LOG_FUNC("(%08lx) %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3]); + break; + case 5: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4]); + break; + case 6: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5]); + break; + case 7: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6]); + break; + case 8: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7]); + break; + case 9: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8]); + break; + case 10: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9]); + break; + case 11: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10]); + break; + case 12: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + LOG_FUNC("(%08lx) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + (UINT_32)pucStartAddr, + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + default: + break; + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); + + return; +} /* end of dumpMemory8() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in double words. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +dumpMemory32 ( + IN PUINT_32 pu4StartAddr, + IN UINT_32 u4Length) +{ + PUINT_8 pucAddr; + + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pu4StartAddr, u4Length); + + if (IS_NOT_ALIGN_4((UINT_32)pu4StartAddr)) { + UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((UINT_32)pu4StartAddr % 4); + + + u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length: u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (PUINT_8) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%08lx) %02x------\n", + (UINT_32)pu4StartAddr, + pucAddr[0]); + break; + case 2: + LOG_FUNC("(%08lx) %02x%02x----\n", + (UINT_32)pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%08lx) %02x%02x%02x--\n", + (UINT_32)pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (PUINT_32)((UINT_32)pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%08lx) %08lx %08lx %08lx %08lx\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } + else { + switch (u4Length) { + case 1: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%08lx) ------%02x\n", + (UINT_32)pu4StartAddr, + pucAddr[0]); + break; + case 2: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%08lx) ----%02x%02x\n", + (UINT_32)pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%08lx) --%02x%02x%02x\n", + (UINT_32)pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%08lx) %08lx\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0]); + break; + case 5: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%08lx) %08lx ------%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], + pucAddr[0]); + break; + case 6: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%08lx) %08lx ----%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], + pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%08lx) %08lx --%02x%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%08lx) %08lx %08lx\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%08lx) %08lx %08lx ------%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pucAddr[0]); + break; + case 10: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%08lx) %08lx %08lx ----%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pucAddr[1], pucAddr[0]); + break; + case 11: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%08lx) %08lx %08lx --%02x%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%08lx) %08lx %08lx %08lx\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); + break; + case 13: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%08lx) %08lx %08lx %08lx ------%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[0]); + break; + case 14: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%08lx) %08lx %08lx %08lx ----%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[1], pucAddr[0]); + break; + case 15: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%08lx) %08lx %08lx %08lx --%02x%02x%02x\n", + (UINT_32)pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + u4Length = 0; + } + } + + return; +} /* end of dumpMemory32() */ +#elif CFG_SUPPORT_XLOG + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +dumpMemory8 ( + IN UINT_32 log_level, + IN PUINT_8 pucStartAddr, + IN UINT_32 u4Length + ) +{ + ASSERT(pucStartAddr); + + if (log_level == ANDROID_LOG_ERROR) { + xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + } + else if (log_level == ANDROID_LOG_WARN) { + xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + } + else if (log_level == ANDROID_LOG_INFO) { + xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + } + else if (log_level == ANDROID_LOG_DEBUG) { + xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + } + else if (log_level == ANDROID_LOG_VERBOSE) { + xlog_printk(ANDROID_LOG_VERBOSE, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } + else { + switch (u4Length) { + case 1: + XLOG_FUNC(log_level, "%02x\n", + pucStartAddr[ 0]); + break; + case 2: + XLOG_FUNC(log_level, "%02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1]); + break; + case 3: + XLOG_FUNC(log_level, "%02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2]); + break; + case 4: + XLOG_FUNC(log_level, "%02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3]); + break; + case 5: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4]); + break; + case 6: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5]); + break; + case 7: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6]); + break; + case 8: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7]); + break; + case 9: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8]); + break; + case 10: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9]); + break; + case 11: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10]); + break; + case 12: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + XLOG_FUNC(log_level, "%02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3], + pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7], + pucStartAddr[ 8], pucStartAddr[ 9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + default: + break; + } + u4Length = 0; + } + } + + + return; +} /* end of dumpMemory8() */ +#endif /* DBG */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c new file mode 100755 index 000000000000..41b179dde04e --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c @@ -0,0 +1,3898 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_bow.c#1 $ +*/ + +/*! \file wlan_bow.c + \brief This file contains the 802.11 PAL commands processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_bow.c $ + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 01 09 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00110632] [Rose][LCA42][Cross Feature][Bluetooth]The "KE" pops up after the device reboots automatically.(once) + * + * Fix bow link disconnected event dereference. + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 07 06 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Improve BoW connection establishment speed. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 21 2011 terry.wu + * NULL + * Fix BoW KE. + * + * 06 20 2011 terry.wu + * NULL + * Add BoW Rate Limitation. + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 07 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * aware more compile options. + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 23 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add some BoW error handling. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * . + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Only reply probe response to its peer or mached SSID for BoW AP. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW SAA retry and disable disconnect event when AAA fail . + * + * 05 21 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Protect BoW connection establishment. + * + * 05 17 2011 terry.wu + * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting + * Send deauth while disconnecting BoW link. + * + * 05 17 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix wrong StaRec state of BoW . + * + * 05 06 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix BoW Multiple Physical Link connect/disconnect issue. + * + * 05 03 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix prAssocRspSwRfb casting. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 12 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add WMM IE for BOW initiator data. + * + * 04 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 28 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Simplify link disconnected routine, remove link disconnected other routine. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add new feature - multiple physical link support. + * + * 02 22 2011 wh.su + * [WCXRP00000486] [MT6620 Wi-Fi][BOW] Fixed the bow send frame but not encrypted issue + * fixed the BOW packet sending without encrypted issue. + * + * 02 21 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BOW link disconnection bug. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting. + * + * 02 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW channel granted function. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW Activity Report structure and bug fix. + * + * 01 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW to support multiple physical link. + * + * 12 08 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support concurrent networks. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 11 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BoW timer assert issue. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix for event returnning Band. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix wrong BoW event size. + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 chinghwa.yu + * NULL + * Fix bowResponderScanDone error when prBssDesc is NULL. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 09 14 2010 cp.wu + * NULL + * indicate correct AIS network information for PAL. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 24 2010 chinghwa.yu + * NULL + * Initialize nicActivateNetwork(prAdapter as soon as bow is starting.. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * 2) command sequence number is now increased atomically + * * 3) private data could be hold and taken use for other purpose +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +#if CFG_BOW_TEST +extern UINT_32 g_arBowRevPalPacketTime[32]; +#endif + + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +static UINT_32 g_u4LinkCount = 0; +static UINT_32 g_u4Beaconing = 0; +static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +const BOW_CMD_T arBowCmdTable[] = { + {BOW_CMD_ID_GET_MAC_STATUS, bowCmdGetMacStatus}, + {BOW_CMD_ID_SETUP_CONNECTION, bowCmdSetupConnection}, + {BOW_CMD_ID_DESTROY_CONNECTION, bowCmdDestroyConnection}, + {BOW_CMD_ID_SET_PTK, bowCmdSetPTK}, + {BOW_CMD_ID_READ_RSSI, bowCmdReadRSSI}, + {BOW_CMD_ID_READ_LINK_QUALITY, bowCmdReadLinkQuality}, + {BOW_CMD_ID_SHORT_RANGE_MODE, bowCmdShortRangeMode}, + {BOW_CMD_ID_GET_CHANNEL_LIST, bowCmdGetChannelList}, +}; + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCID, + IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, + IN PUINT_8 pucInfoBuffer, + IN UINT_8 ucSeqNumber + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, ("Command ID = 0x%08X\n", ucCID)); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, ("ucCmdSeqNum =%d\n", ucCmdSeqNum)); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_BOW_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + prCmdInfo->u4PrivateData = (UINT_32) ucSeqNumber; + + // Setup WIFI_CMD_T (no payload) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if(u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) { + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dispatch command coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanbowHandleCommand( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + WLAN_STATUS retval = WLAN_STATUS_FAILURE; + UINT_16 i; + + ASSERT(prAdapter); + + for (i = 0; i < sizeof(arBowCmdTable) / sizeof(BOW_CMD_T); i++) { + if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && + arBowCmdTable[i].pfCmdHandle) { + retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); + break; + } + } + + return retval; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_MAC_STATUS +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdGetMacStatus( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_MAC_STATUS prMacStatus; + UINT_8 idx = 0; + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eBssSCO; + UINT_8 ucNumOfChannel = 0;//MAX_BOW_NUMBER_OF_CHANNEL; + + RF_CHANNEL_INFO_T aucChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; + + ASSERT(prAdapter); + + //3 <1> If LinkCount != 0 -> OK (optional) + + eBand = BAND_2G4; + eBssSCO = CHNL_EXT_SCN; + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS)), VIR_MEM_TYPE); + + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_MAC_STATUS); + + // fill event body + prMacStatus = (P_BOW_MAC_STATUS)(prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(BOW_MAC_STATUS)); + + //3 <2> Call CNM to decide if BOW available. + if (cnmBowIsPermitted(prAdapter)) + { + prMacStatus->ucAvailability = TRUE; + } + else + { + prMacStatus->ucAvailability = FALSE; + } + + memcpy(prMacStatus->aucMacAddr, prAdapter->rWifiVar.aucDeviceAddress, PARAM_MAC_ADDR_LEN); + + if (cnmPreferredChannel(prAdapter, &eBand, &ucPrimaryChannel, &eBssSCO)) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdGetMacStatus, Get preferred channel.\n")); +#endif + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } + else + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel)); +#endif + + rlmDomainGetChnlList(prAdapter, BAND_2G4, MAX_BOW_NUMBER_OF_CHANNEL_2G4, &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel/*MAX_BOW_NUMBER_OF_CHANNEL_2G4*/; idx++) + { + prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = ucNumOfChannel; + } + + rlmDomainGetChnlList(prAdapter, BAND_5G, MAX_BOW_NUMBER_OF_CHANNEL_5G, &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel/*MAX_BOW_NUMBER_OF_CHANNEL_5G*/; idx++) + { + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = prMacStatus->ucNumOfChannel + ucNumOfChannel; + + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("ucNumOfChannel, eBand, aucChannelList, %x, %x, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + ucNumOfChannel, + aucChannelList[0].eBand, + aucChannelList[0].ucChannelNum, + aucChannelList[1].ucChannelNum, + aucChannelList[2].ucChannelNum, + aucChannelList[3].ucChannelNum, + aucChannelList[4].ucChannelNum, + aucChannelList[5].ucChannelNum, + aucChannelList[6].ucChannelNum, + aucChannelList[7].ucChannelNum, + aucChannelList[8].ucChannelNum, + aucChannelList[9].ucChannelNum, + aucChannelList[10].ucChannelNum, + aucChannelList[11].ucChannelNum, + aucChannelList[12].ucChannelNum, + aucChannelList[13].ucChannelNum, + aucChannelList[14].ucChannelNum, + aucChannelList[15].ucChannelNum, + aucChannelList[16].ucChannelNum, + aucChannelList[17].ucChannelNum)); + + DBGLOG(BOW, EVENT, ("prMacStatus->ucNumOfChannel, eBand, prMacStatus->arChannelList, %x, %x, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->ucNumOfChannel, + prMacStatus->arChannelList[0].ucChannelBand, + prMacStatus->arChannelList[0].ucChannelNum, + prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, + prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, + prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, + prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, + prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, + prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, + prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, + prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, + prMacStatus->arChannelList[17].ucChannelNum)); + + DBGLOG(BOW, EVENT, ("prMacStatus->ucNumOfChannel, %x.\n", prMacStatus->ucNumOfChannel)); + DBGLOG(BOW, EVENT, ("prMacStatus->arChannelList[0].ucChannelBand, %x.\n", prMacStatus->arChannelList[0].ucChannelBand)); + DBGLOG(BOW, EVENT, ("prMacStatus->arChannelList[0].ucChannelNum, %x.\n", prMacStatus->arChannelList[0].ucChannelNum)); + DBGLOG(BOW, EVENT, ("prMacStatus->ucAvailability, %x.\n", prMacStatus->ucAvailability)); + DBGLOG(BOW, EVENT, ("prMacStatus->aucMacAddr, %x:%x:%x:%x:%x:%x.\n", + prMacStatus->aucMacAddr[0], + prMacStatus->aucMacAddr[1], + prMacStatus->aucMacAddr[2], + prMacStatus->aucMacAddr[3], + prMacStatus->aucMacAddr[4], + prMacStatus->aucMacAddr[5])); +#endif + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SETUP_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdSetupConnection( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_SETUP_CONNECTION prBowSetupConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + + UINT_8 ucBowTableIdx = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowSetupConnection = (P_BOW_SETUP_CONNECTION) &(prCmd->aucPayload[0]); + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(BOW_SETUP_CONNECTION)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_INVALID_LENGTH; + } + + //3 <1> If ucLinkCount >= 4 -> Fail. + if (g_u4LinkCount >= CFG_BOW_PHYSICAL_LINK_NUM) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + //3 <2> Call CNM, check if BOW is available. + if (!cnmBowIsPermitted(prAdapter)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + //3 <3> Lookup BOW Table, if Peer MAC address exist and valid -> Fail. + if (bowCheckBowTableIfVaild(prAdapter, prBowSetupConnection->aucPeerAddress)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if(EQUAL_MAC_ADDR(prBowSetupConnection->aucPeerAddress, prAdapter->rWifiVar.aucDeviceAddress)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_NOT_ACCEPTED; + } + + + // fill CMD_BT_OVER_WIFI + rCmdBtOverWifi.ucAction = BOW_SETUP_CMD; + rCmdBtOverWifi.ucChannelNum = prBowSetupConnection->ucChannelNum; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowSetupConnection->aucPeerAddress); + rCmdBtOverWifi.u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + rCmdBtOverWifi.ucTimeoutDiscovery = prBowSetupConnection->ucTimeoutDiscovery; + rCmdBtOverWifi.ucTimeoutInactivity = prBowSetupConnection->ucTimeoutInactivity; + rCmdBtOverWifi.ucRole = prBowSetupConnection->ucRole; + rCmdBtOverWifi.PAL_Capabilities = prBowSetupConnection->ucPAL_Capabilities; + rCmdBtOverWifi.cMaxTxPower = prBowSetupConnection->cMaxTxPower; + + if (prBowSetupConnection->ucChannelNum > 14) { + rCmdBtOverWifi.ucChannelBand = BAND_5G; + } + else { + rCmdBtOverWifi.ucChannelBand = BAND_2G4; + } + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowSetupConnection->aucPeerAddress); + +#if CFG_BOW_PHYSICAL_LINK_NUM > 1 + /*Channel check for supporting multiple physical link*/ + if(g_u4LinkCount > 0) { + if (prBowSetupConnection->ucChannelNum != prBowFsmInfo->ucPrimaryChannel) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + } +#endif + + prBowFsmInfo->ucPrimaryChannel = prBowSetupConnection->ucChannelNum; + prBowFsmInfo->eBand = rCmdBtOverWifi.ucChannelBand; + prBowFsmInfo->u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + prBowFsmInfo->ucRole = prBowSetupConnection->ucRole; + + if (prBowSetupConnection->ucPAL_Capabilities > 0) + { + prBowFsmInfo->fgSupportQoS = TRUE; + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdSetupConnection.\n")); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Channel Number - 0x%x.\n", rCmdBtOverWifi.ucChannelNum)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Peer address - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], + rCmdBtOverWifi.rPeerAddr[2], + rCmdBtOverWifi.rPeerAddr[3], + rCmdBtOverWifi.rPeerAddr[4], + rCmdBtOverWifi.rPeerAddr[5])); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Beacon interval - 0x%x.\n", rCmdBtOverWifi.u2BeaconInterval)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Timeout activity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutDiscovery)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Timeout inactivity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutInactivity)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Role - 0x%x.\n", rCmdBtOverWifi.ucRole)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi PAL capability - 0x%x.\n", rCmdBtOverWifi.PAL_Capabilities)); + DBGLOG(BOW, EVENT, ("rCmdBtOverWifi Max Tx power - 0x%x.\n", rCmdBtOverWifi.cMaxTxPower)); +#endif + + //3 <4> Get a free BOW entry, mark as Valid, fill in Peer MAC address, LinkCount += 1, state == Starting. + if (!bowGetBowTableFreeEntry(prAdapter, &ucBowTableIdx)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + prBowFsmInfo->prTargetBssDesc = NULL; + + COPY_MAC_ADDR(rBowTable.aucPeerAddress, prBowSetupConnection->aucPeerAddress); + //owTable.eState = BOW_DEVICE_STATE_ACQUIRING_CHANNEL; + rBowTable.fgIsValid = TRUE; + rBowTable.ucAcquireID = prBowFsmInfo->ucSeqNumOfChReq; + //rBowTable.ucRole = prBowSetupConnection->ucRole; + //rBowTable.ucChannelNum = prBowSetupConnection->ucChannelNum; + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + kalSetBowRole(prAdapter->prGlueInfo, rCmdBtOverWifi.ucRole, prBowSetupConnection->aucPeerAddress); + + GLUE_INC_REF_CNT(g_u4LinkCount); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount)); +#endif + + if (g_u4LinkCount == 1) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowStarting, cnmTimerInitTimer.\n")); + DBGLOG(BOW, EVENT, ("prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval)); +#endif + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC)bowSendBeacon, + (UINT_32)NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC)bowChGrantedTimeout, + (UINT_32)NULL); + + //Reset Global Variable + g_u4Beaconing = 0; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount)); + DBGLOG(BOW, EVENT, ("kalInitBowDevice, bow0\n")); +#endif +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network*/ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + + if(rCmdBtOverWifi.ucRole == BOW_INITIATOR) { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } else { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + bowResponderScan(prAdapter); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_DESTROY_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdDestroyConnection( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_DESTROY_CONNECTION prBowDestroyConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; +#if CFG_BOW_TEST + UINT_8 ucIdx; +#endif + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + //3 <1> If LinkCount == 0 ->Fail (Optional) + if (g_u4LinkCount == 0) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(BOW_DESTROY_CONNECTION)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + + //3 <2> Lookup BOW table, check if is not exist (Valid and Peer MAC address) -> Fail + prBowDestroyConnection = (P_BOW_DESTROY_CONNECTION) &(prCmd->aucPayload[0]); + + if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n")); +#endif + return WLAN_STATUS_NOT_ACCEPTED; + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdDestroyConnection, destroy Peer address - %x:%x:%x:%x:%x:%x.\n", prBowDestroyConnection->aucPeerAddress[0], + prBowDestroyConnection->aucPeerAddress[1], + prBowDestroyConnection->aucPeerAddress[2], + prBowDestroyConnection->aucPeerAddress[3], + prBowDestroyConnection->aucPeerAddress[4], + prBowDestroyConnection->aucPeerAddress[5])); +#endif + + // fill CMD_BT_OVER_WIFI + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdDestroyConnection, rCmdBtOverWifi.rPeerAddr - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], + rCmdBtOverWifi.rPeerAddr[2], + rCmdBtOverWifi.rPeerAddr[3], + rCmdBtOverWifi.rPeerAddr[4], + rCmdBtOverWifi.rPeerAddr[5])); +#endif + +#if CFG_BOW_TEST + for (ucIdx = 0; ucIdx < 11; ucIdx++) + { + DBGLOG(BOW, EVENT, ("BoW receiving PAL packet delta time vs packet number -- %d ms vs %x.\n", ucIdx, g_arBowRevPalPacketTime[ucIdx])); + } +#endif + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(CMD_BT_OVER_WIFI), + (PUINT_8) &rCmdBtOverWifi, + prCmd->rHeader.ucSeqNumber + ); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SET_PTK +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdSetPTK( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_SET_PTK prBowSetPTK; + CMD_802_11_KEY rCmdKey; + + ASSERT(prAdapter); + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prBowSetPTK->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucPeerAddress[0], + prBowSetPTK->aucPeerAddress[1], + prBowSetPTK->aucPeerAddress[2], + prBowSetPTK->aucPeerAddress[3], + prBowSetPTK->aucPeerAddress[4], + prBowSetPTK->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("rCmdKey.ucIsAuthenticator, %x.\n", kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress))); +#endif + + if (!bowCheckBowTableIfVaild(prAdapter, prBowSetPTK->aucPeerAddress)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowSetPTK->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + + return WLAN_STATUS_NOT_ACCEPTED; + } + + // fill CMD_802_11_KEY + rCmdKey.ucAddRemove = 1; // add + rCmdKey.ucTxKey = 1; + rCmdKey.ucKeyType = 1; + rCmdKey.ucIsAuthenticator = kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress); + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prBowSetPTK->aucPeerAddress); + rCmdKey.ucNetType = NETWORK_TYPE_BOW_INDEX; // BT Over Wi-Fi + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; // AES + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; // AES = 128bit + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prBowSetPTK->aucTemporalKey, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucTemporalKey[0], + prBowSetPTK->aucTemporalKey[1], + prBowSetPTK->aucTemporalKey[2], + prBowSetPTK->aucTemporalKey[3], + prBowSetPTK->aucTemporalKey[4], + prBowSetPTK->aucTemporalKey[5], + prBowSetPTK->aucTemporalKey[6], + prBowSetPTK->aucTemporalKey[7], + prBowSetPTK->aucTemporalKey[8], + prBowSetPTK->aucTemporalKey[9], + prBowSetPTK->aucTemporalKey[10], + prBowSetPTK->aucTemporalKey[11], + prBowSetPTK->aucTemporalKey[12], + prBowSetPTK->aucTemporalKey[13], + prBowSetPTK->aucTemporalKey[14], + prBowSetPTK->aucTemporalKey[15])); + + DBGLOG(BOW, EVENT, ("rCmdKey.aucKeyMaterial, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + rCmdKey.aucKeyMaterial[0], + rCmdKey.aucKeyMaterial[1], + rCmdKey.aucKeyMaterial[2], + rCmdKey.aucKeyMaterial[3], + rCmdKey.aucKeyMaterial[4], + rCmdKey.aucKeyMaterial[5], + rCmdKey.aucKeyMaterial[6], + rCmdKey.aucKeyMaterial[7], + rCmdKey.aucKeyMaterial[8], + rCmdKey.aucKeyMaterial[9], + rCmdKey.aucKeyMaterial[10], + rCmdKey.aucKeyMaterial[11], + rCmdKey.aucKeyMaterial[12], + rCmdKey.aucKeyMaterial[13], + rCmdKey.aucKeyMaterial[14], + rCmdKey.aucKeyMaterial[15])); +#endif + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(CMD_802_11_KEY), + (PUINT_8) &rCmdKey, + prCmd->rHeader.ucSeqNumber + ); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_RSSI +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdReadRSSI( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_READ_RSSI prBowReadRSSI; + + ASSERT(prAdapter); + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(BOW_READ_RSSI)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prBowReadRSSI = (P_BOW_READ_RSSI) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, + 0, + NULL, + prCmd->rHeader.ucSeqNumber + ); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_LINK_QUALITY +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdReadLinkQuality( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; + + ASSERT(prAdapter); + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(P_BOW_READ_LINK_QUALITY)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prBowReadLinkQuality = (P_BOW_READ_LINK_QUALITY) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, + 0, + NULL, + prCmd->rHeader.ucSeqNumber + ); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SHORT_RANGE_MODE +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdShortRangeMode( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; + CMD_TX_PWR_T rTxPwrParam; + + ASSERT(prAdapter); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdShortRangeMode.\n")); +#endif + + prBowShortRangeMode = (P_BOW_SHORT_RANGE_MODE) &(prCmd->aucPayload[0]); + + // parameter size check + if(prCmd->rHeader.u2PayloadLength != sizeof(BOW_SHORT_RANGE_MODE)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (!bowCheckBowTableIfVaild(prAdapter, prBowShortRangeMode->aucPeerAddress)) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowShortRangeMode->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_NOT_ACCEPTED; + } + + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prBowShortRangeMode->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowShortRangeMode->aucPeerAddress[0], + prBowShortRangeMode->aucPeerAddress[1], + prBowShortRangeMode->aucPeerAddress[2], + prBowShortRangeMode->aucPeerAddress[3], + prBowShortRangeMode->aucPeerAddress[4], + prBowShortRangeMode->aucPeerAddress[5])); +#endif + + rTxPwrParam.cTxPwr2G4Cck = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GOFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GHT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + if (nicUpdateTxPower(prAdapter, &rTxPwrParam) == WLAN_STATUS_SUCCESS) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS)); +#endif + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + else + { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_CHANNEL_LIST +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowCmdGetChannelList( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ) +{ + ASSERT(prAdapter); + + // not supported yet + return WLAN_STATUS_FAILURE; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventSetStatus( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd, + IN UINT_8 ucEventBuf + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + // fill event body + prBowCmdStatus = (P_BOW_COMMAND_STATUS)(prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventSetCommon( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + // fill event body + prBowCmdStatus = (P_BOW_COMMAND_STATUS)(prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventLinkConnected( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + // fill event body + prBowLinkConnected = (P_BOW_LINK_CONNECTED)(prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId)); + DBGLOG(BOW, EVENT, ("prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber)); + DBGLOG(BOW, EVENT, ("prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength)); + DBGLOG(BOW, EVENT, ("prBowLinkConnected->rChannel.ucChannelNum, 0x%x\n", prBowLinkConnected->rChannel.ucChannelNum)); + DBGLOG(BOW, EVENT, ("prBowLinkConnected->rChannel.ucChannelBand, 0x%x\n", prBowLinkConnected->rChannel.ucChannelBand)); + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkConnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkConnected, prBowLinkConnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkConnected->aucPeerAddress[0], + prBowLinkConnected->aucPeerAddress[1], + prBowLinkConnected->aucPeerAddress[2], + prBowLinkConnected->aucPeerAddress[3], + prBowLinkConnected->aucPeerAddress[4], + prBowLinkConnected->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkConnected, g_u4LinkCount, %x.\n", g_u4LinkCount)); +#endif + + /*Indicate Event to PAL*/ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED))); + + /*Release channel if granted*/ + if(prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + //bowReleaseCh(prAdapter); + /*Requested, not granted yet*/ + } else if(prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + } + + /* set to connected status*/ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTED); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventLinkDisconnected( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + UINT_8 ucBowTableIdx; + ENUM_BOW_DEVICE_STATE eFsmState; + BOOL fgSendDeauth = FALSE; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + if(eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing*/ + return; + } + /*Cancel scan*/ + else if(eFsmState == BOW_DEVICE_STATE_SCANNING && + !(prBowFsmInfo->fgIsChannelRequested)) { + bowResponderCancelScan(prAdapter, FALSE); + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_DISCONNECTING); + return; + } + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + { + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + } + else + { + prEvent->rHeader.ucSeqNumber = 0; + } + + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + // fill event body + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED)(prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId)); + DBGLOG(BOW, EVENT, ("prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber)); + DBGLOG(BOW, EVENT, ("prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength)); + + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkDisconnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkDisconnected, prBowLinkDisconnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkDisconnected->aucPeerAddress[0], + prBowLinkDisconnected->aucPeerAddress[1], + prBowLinkDisconnected->aucPeerAddress[2], + prBowLinkDisconnected->aucPeerAddress[3], + prBowLinkDisconnected->aucPeerAddress[4], + prBowLinkDisconnected->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkDisconnected, g_u4LinkCount, %x.\n", g_u4LinkCount)); +#endif + + /*Indicate BoW event to PAL*/ +#if 0 + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); +#endif + + // set to disconnected status + prBowFsmInfo->prTargetStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_BOW_INDEX, prBowLinkDisconnected->aucPeerAddress); + + /*Release channel if granted*/ + if(prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + /*Requested, not granted yet*/ + } else if(prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + //bowReleaseCh(prAdapter); + } + +#if 1 + /*Send Deauth to connected peer*/ + if (eFsmState == BOW_DEVICE_STATE_CONNECTED && + (prBowFsmInfo->prTargetStaRec->ucStaState == STA_STATE_3)) + { + fgSendDeauth = TRUE; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress))); +#endif + authSendDeauthFrame(prAdapter, + prBowFsmInfo->prTargetStaRec, + (P_SW_RFB_T)NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, + (PFN_TX_DONE_HANDLER)bowDisconnectLink); + } +#endif + +#if 0 + //3 <3>Stop this link; flush Tx; send deAuthentication -> abort. SAA, AAA. need to check BOW table state == Connected. + if (prAdapter->prGlueInfo->i4TxPendingFrameNum > 0) { + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + } + + /* flush pending security frames */ + if (prAdapter->prGlueInfo->i4TxPendingSecurityFrameNum > 0) { + kalClearSecurityFrames(prAdapter->prGlueInfo); + } +#endif + + /*Update BoW table*/ + bowGetBowTableEntryByPeerAddress(prAdapter, prBowLinkDisconnected->aucPeerAddress, &ucBowTableIdx); + rBowTable.fgIsValid = FALSE; + rBowTable.eState = BOW_DEVICE_STATE_DISCONNECTED; + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL*/ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + + /*Decrease link count*/ + GLUE_DEC_REF_CNT(g_u4LinkCount); + + /*If no need to send deauth, DO disconnect now*/ + /*If need to send deauth, DO disconnect at deauth Tx done*/ + if(!fgSendDeauth){ + bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventSetSetupConnection ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BT_OVER_WIFI prCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + // restore original command for rPeerAddr + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (P_CMD_BT_OVER_WIFI)(prWifiCmd->aucBuffer); + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + // fill event body + prBowCmdStatus = (P_BOW_COMMAND_STATUS)(prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL*/ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + + // set to starting status + kalSetBowState(prAdapter->prGlueInfo, + BOW_DEVICE_STATE_STARTING, + prCmdBtOverWifi->rPeerAddr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_LINK_QUALITY +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventReadLinkQuality ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_LINK_QUALITY prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY)pucEventBuf; + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_QUALITY); + + // fill event body + prBowLinkQuality = (P_BOW_LINK_QUALITY)(prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (UINT_8)prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_RSSI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdEventReadRssi ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_RSSI prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY)pucEventBuf; + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_RSSI); + + // fill event body + prBowRssi = (P_BOW_RSSI)(prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(BOW_RSSI)); + prBowRssi->cRssi = (INT_8) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the default command timeout handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanbowCmdTimeoutHandler ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + // fill event header + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + // fill event body + prBowCmdStatus = (P_BOW_COMMAND_STATUS)(prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; // timeout + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + + return; +} + + +VOID +bowStopping( + IN P_ADAPTER_T prAdapter + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBowBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowStoping.\n")); + DBGLOG(BOW, EVENT, ("bowStoping, SSID %s.\n", prBowBssInfo->aucSSID)); + DBGLOG(BOW, EVENT, ("bowStoping, prBowBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucBSSID[0], + prBowBssInfo->aucBSSID[1], + prBowBssInfo->aucBSSID[2], + prBowBssInfo->aucBSSID[3], + prBowBssInfo->aucBSSID[4], + prBowBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, ("bowStoping, prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucOwnMacAddr[0], + prBowBssInfo->aucOwnMacAddr[1], + prBowBssInfo->aucOwnMacAddr[2], + prBowBssInfo->aucOwnMacAddr[3], + prBowBssInfo->aucOwnMacAddr[4], + prBowBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, ("bowStoping, prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], + prAdapter->rWifiVar.aucDeviceAddress[5])); + DBGLOG(BOW, EVENT, ("bowStopping, g_u4LinkCount, %x.\n", g_u4LinkCount)); + DBGLOG(BOW, EVENT, ("prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); + kalPrint("BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); +#endif + + if (g_u4LinkCount == 0) + { + /*Stop beaconing*/ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network*/ + //prBowBssInfo->fgIsNetActive = FALSE; + //prBowBssInfo->fgIsBeaconActivated = FALSE; + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT*/ + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_BOW_INDEX); + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + + return; +} + + +VOID +bowStarting( + IN P_ADAPTER_T prAdapter + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("BoW Starting.\n")); + DBGLOG(BOW, EVENT, ("BoW channel granted.\n")); +#endif + +#if 0 + /*Active BoW Network*/ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif + + //3 <1> Update BSS_INFO_T per Network Basis + //4 <1.1> Setup Operation Mode + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBssInfo->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prBssInfo->eCurrentOPMode = OP_MODE_BOW; + + //4 <1.2> Setup SSID + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("SSID %s.\n", prBssInfo->aucSSID)); + DBGLOG(BOW, EVENT, ("prBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucBSSID[0], + prBssInfo->aucBSSID[1], + prBssInfo->aucBSSID[2], + prBssInfo->aucBSSID[3], + prBssInfo->aucBSSID[4], + prBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, ("prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucOwnMacAddr[0], + prBssInfo->aucOwnMacAddr[1], + prBssInfo->aucOwnMacAddr[2], + prBssInfo->aucOwnMacAddr[3], + prBssInfo->aucOwnMacAddr[4], + prBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, ("prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], + prAdapter->rWifiVar.aucDeviceAddress[5])); +#endif + + //4 <1.3> Clear current AP's STA_RECORD_T and current AID + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + prBssInfo->u2AssocId = 0; + + //4 <1.4> Setup Channel, Band and Phy Attributes + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + { + prBssInfo->eBand = BAND_2G4; + } + else + { + prBssInfo->eBand = BAND_5G; + } + +#if CFG_BOW_SUPPORT_11N + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) + { + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; //RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } + else + { + //prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ + //prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + + //prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; //RATE_SET_ERP; + //prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; //RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + //4 <1.5> Setup MIB for current BSS + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) + { + prAdapter->rWifiVar.fgSupportQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + + + //3 <2> Update BSS_INFO_T common part +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + //3 <3> Set MAC HW + + //4 <2> Initiate BSS_INFO_T - common part + BOW_BSS_INFO_INIT(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); +#endif + + //4 <3.1> use command packets to inform firmware + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + //4 <3.2> Update AdHoc PM parameter + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_BOW_INDEX); + + //4 <3.1> Reset HW TSF Update Mode and Beacon Mode + + //4 <3.2> Setup BSSID + // TODO: rxmSetRxFilterBSSID0 +// rxmSetRxFilterBSSID0(prBssInfo->ucHwBssidId, prBssInfo->aucBSSID); + + //4 <3.3> Setup RX Filter to accept Probe Request + // TODO: f get/set RX filter. + +#if 0 + { + UINT_32 u4RxFilter; + if (halMacRxGetRxFilters(&u4RxFilter)== HAL_STATUS_SUCCESS) { + + u4RxFilter &= ~BIT(RXFILTER_DROP_PROBE_REQ); + + halMacRxSetRxFilters(u4RxFilter); + } + } +#endif + } + + /*Update BoW Table*/ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_STARTING); + +#if CFG_BOW_TEST + kalPrint("BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, ("bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount)); +#endif + + /*Start beaconing*/ + if (g_u4Beaconing < 1) + { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } + +#if 0 + /*Responder: Start to scan Initiator*/ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowStarting responder, start scan result searching.\n")); +#endif + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder*/ + else { + //bowRequestCh(prAdapter); + } +#endif + return; +} + +VOID +bowAssignSsid ( + IN PUINT_8 pucSsid, + IN PUINT_8 puOwnMacAddr + ) +{ + UINT_8 i; + UINT_8 aucSSID[]=BOW_WILDCARD_SSID; + + kalMemCopy(pucSsid, aucSSID, BOW_WILDCARD_SSID_LEN); + + for (i = 0; i < 6; i++) + { + pucSsid[(3 * i) + 3] = 0x2D; + if ((*(puOwnMacAddr + i) >> 4) < 0xA) + { + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x30; + } + else + { + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x57; + } + + if ((*(puOwnMacAddr + i) & 0x0F) < 0xA) + { + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x30; + } + else + { + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x57; + } + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +bowValidateProbeReq( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + +#if 0//CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateProbeReq.\n")); +#endif + + //4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8)((UINT_32)prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T)pucIE; + } + break; + } + } /* end of IE_FOR_EACH */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T)pucIE; + } + break; + } + } /* end of IE_FOR_EACH */ + + //4 <2> Check network conditions + /*If BoW AP is beaconing*/ + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW && + g_u4Beaconing > 0) { + + /*Check the probe requset sender is our peer*/ + if(bowCheckBowTableIfVaild(prAdapter, prMgtHdr->aucSrcAddr)) { + fgReplyProbeResp = TRUE; + } + /*Check the probe request target SSID is our SSID*/ + else if ((prIeSsid) && + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + else { + fgReplyProbeResp = FALSE; + } + } + + return fgReplyProbeResp; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowSendBeacon( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) + { + //Send beacon + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if CFG_BOW_TEST + else { + kalPrint("BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + } +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowResponderScan( + IN P_ADAPTER_T prAdapter + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowResponderScan.\n")); + kalPrint("BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq+1); +#endif + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + + if (!prScanReqMsg) + { + ASSERT(0); // Can't trigger SCAN FSM + return; + } + + /*Fill scan message*/ + prScanReqMsg->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_BOW_INDEX; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDLength = BOW_SSID_LEN; + bowAssignSsid(prScanReqMsg->aucSSID, prBowFsmInfo->aucPeerAddress); + prScanReqMsg->ucChannelListNum = 1; + + if (prBowFsmInfo->eBand == BAND_2G4) + { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_2G4; + } + else + { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_5G; + } + + prScanReqMsg->arChnlInfoList[0].ucChannelNum = prBowFsmInfo->ucPrimaryChannel; + prScanReqMsg->u2IELen = 0; + + /*Send scan message*/ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + + /*Change state to SCANNING*/ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + + //prBowFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowResponderScanDone( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_DESC_T prBssDesc; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_BOW_DEVICE_STATE eFsmState; + ENUM_SCAN_STATUS eScanStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + ASSERT(prScanDoneMsg->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowResponderScanDone.\n")); + kalPrint("BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); +#endif + + if( eScanStatus == SCAN_STATUS_CANCELLED) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); +#endif + if(eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); + } + return; + } + else if(eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + //bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); + return; + } + else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) + { + DBGLOG(BOW, EVENT, ("Sequence no. of BOW Responder scan done is not matched.\n")); + return; + } + else + { + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("End scan result searching.\n")); +#endif + + /*Initiator is FOUND*/ + if (prBssDesc != NULL)// (prBssDesc->aucBSSID != NULL)) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Search Bow Peer address - %x:%x:%x:%x:%x:%x.\n", prBssDesc->aucBSSID[0], + prBssDesc->aucBSSID[1], + prBssDesc->aucBSSID[2], + prBssDesc->aucBSSID[3], + prBssDesc->aucBSSID[4], + prBssDesc->aucBSSID[5])); + DBGLOG(BOW, EVENT, ("Starting to join initiator.\n")); +#endif + /*Set target BssDesc*/ + prBowFsmInfo->prTargetBssDesc = prBssDesc; + /*Request channel to do JOIN*/ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } + /*Initiator is NOT FOUND*/ + else + { + /*Scan again, until PAL timeout*/ + bowResponderScan(prAdapter); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); +#endif + } + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for cancelling scan request. There is another option to extend channel privilige +* for another purpose. +* +* @param fgIsChannelExtention - Keep the channel previlege, but can cancel scan timer. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowResponderCancelScan ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsChannelExtention + ) +{ + + P_MSG_SCN_SCAN_CANCEL prScanCancel = (P_MSG_SCN_SCAN_CANCEL)NULL; + P_BOW_FSM_INFO_T prBowFsmInfo = (P_BOW_FSM_INFO_T)NULL; + + DEBUGFUNC("bowResponderCancelScan()"); + + do { + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (TRUE) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); +#endif + /* There is a channel privilege on hand. */ + + DBGLOG(P2P, TRACE, ("BOW Cancel Scan\n")); + + prScanCancel = (P_MSG_SCN_SCAN_CANCEL)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancel) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, ("Buffer not enough, can not cancel scan.\n")); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; +#if CFG_ENABLE_WIFI_DIRECT + prScanCancel->fgIsChannelExt = fgIsChannelExtention; +#endif + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prScanCancel, + MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); + +} /* bowResponderCancelScan */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowResponderJoin( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + ASSERT(prBssDesc); + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, ("Starting bowResponderJoin.\n")); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + //4 <1> We are going to connect to this BSS. + prBssDesc->fgIsConnecting = TRUE; + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTING); + + //4 <2> Setup corresponding STA_RECORD_T + /*Support First JOIN and retry*/ + prStaRec = bssCreateStaRecFromBssDesc( + prAdapter, + STA_TYPE_BOW_AP, + NETWORK_TYPE_BOW_INDEX, + prBssDesc); + + prBowFsmInfo->prTargetStaRec = prStaRec; + + //4 <3> Update ucAvailableAuthTypes which we can choice during SAA + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (UINT_8)AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + + //4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes + if (prBowFsmInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, ("JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n")); + prBowFsmInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } + else { + ASSERT(0); + } + + //4 <4.1> sync. to firmware domain + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + //4 <5> Overwrite Connection Setting for eConnectionPolicy + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID)); + DBGLOG(BOW, EVENT, ("bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID)); +#endif + } + + //4 <6> Send a Msg to trigger SAA to start JOIN process. + prJoinReqMsg = (P_MSG_JOIN_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); // Can't trigger SAA FSM + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_BOW_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + prBssInfo->prStaRecOfAP = prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("prStaRec->eStaType, %x.\n", prStaRec->eStaType)); + printk("BoW trigger SAA ["MACSTR"]\n", MAC2STR(prStaRec->aucMacAddr)); +#endif + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for BOW FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowFsmRunEventJoinComplete( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + P_BSS_INFO_T prBssInfo; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T)prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Start bowfsmRunEventJoinComplete.\n")); + DBGLOG(BOW, EVENT, ("bowfsmRunEventJoinComplete ptr check\n")); + DBGLOG(BOW, EVENT, ("prMsgHdr %x\n", prMsgHdr)); + DBGLOG(BOW, EVENT, ("prAdapter %x\n", prAdapter)); + DBGLOG(BOW, EVENT, ("prBowFsmInfo %x\n", prBowFsmInfo)); + DBGLOG(BOW, EVENT, ("prStaRec %x\n", prStaRec)); +#endif + + ASSERT(prStaRec); + ASSERT(prBowFsmInfo); + + // Check SEQ NUM + if (prJoinCompMsg->ucSeqNum == prBowFsmInfo->ucSeqNumOfReqMsg) { + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + //4 <1> JOIN was successful + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + //4 <1.2>Update Rate Set + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | + RATE_SET_BIT_48M | + RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the avaliable highest rate*/ + if(prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + //4 <1.1> Change FW's Media State immediately. + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + //4 <1.2> Update HT information and set channel + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ +#if CFG_BOW_SUPPORT_11N + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); +#endif + + //4 <1.3> Update BSS_INFO_T + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Finish bowUpdateBssInfoForJOIN.\n")); +#endif + //4 <1.4> Activate current AP's STA_RECORD_T in Driver. + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowFsmRunEventJoinComplete, qmActivateStaRec.\n")); +#endif + + //4 <1.7> Set the Next State of BOW FSM + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkConnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); + } + //4 <2> JOIN was not successful + else + { + /*Retry*/ + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); +#endif +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Start bowfsmRunEventJoinComplete -- Join failed.\n")); + printk("BoW trigger SAA REJOIN\n"); +#endif + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowIndicationOfMediaStateToHost ( + IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, + IN BOOLEAN fgDelayIndication + ) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + // NOTE(Kevin): Move following line to bowChangeMediaState() macro per CM's request. + //prBowBssInfo->eConnectionState = eConnectionState; + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + if (prBssInfo->eConnectionStateIndicated == eConnectionState) { + return; + } + } + + if (!fgDelayIndication) { + //4 <0> Cancel Delay Timer + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rIndicationOfDisconnectTimer); + + //4 <1> Fill EVENT_CONNECTION_STATUS + rEventConnStatus.ucMediaStatus = (UINT_8)eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { + rEventConnStatus.ucInfraMode = (UINT_8)NET_TYPE_INFRA; + rEventConnStatus.u2AID = prBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } + else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (UINT_8)NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = prBssInfo->u2ATIMWindow; + } + else { + ASSERT(0); + } + + COPY_SSID(rEventConnStatus.aucSsid, + rEventConnStatus.ucSsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + COPY_MAC_ADDR(rEventConnStatus.aucBssid, prBssInfo->aucBSSID); + + rEventConnStatus.u2BeaconPeriod = prBssInfo->u2BeaconInterval; + rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prBssInfo->ucPrimaryChannel); + + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_HR_DSSS_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_DS; + break; + } + } + else { + #if CFG_PRIVACY_MIGRATION + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); + #endif + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + //4 <2> Indication + nicMediaStateChange(prAdapter, NETWORK_TYPE_BOW_INDEX, &rEventConnStatus); + prBssInfo->eConnectionStateIndicated = eConnectionState; + } + else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(BOW, INFO, ("Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent)); + + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indiate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowRunEventAAATxFail ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n")); + printk("BoW AAA TxFail, target state %d\n", prStaRec->ucStaState+1); +#endif + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indiate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bowRunEventAAAComplete ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n")); + printk("BoW AAA complete ["MACSTR"]\n", MAC2STR(prStaRec->aucMacAddr)); +#endif + + /*Update BssInfo to connected*/ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*Update StaRec to State3*/ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected*/ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkConnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle RxDeauth +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +bowRunEventRxDeAuth ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if(!IS_STA_IN_BOW(prStaRec)) { + return WLAN_STATUS_NOT_ACCEPTED; + } + + eFsmState = bowGetBowTableState(prAdapter, prStaRec->aucMacAddr); + + if(eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing*/ + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (prStaRec->ucStaState > STA_STATE_1) { + + if (STA_STATE_3 == prStaRec->ucStaState) { + //P_MSG_AIS_ABORT_T prAisAbortMsg; + + /* NOTE(Kevin): Change state immediately to avoid starvation of + * MSG buffer because of too many deauth frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle BoW Link disconnect. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowDisconnectLink ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /*Free target StaRec*/ + if(prMsduInfo) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + } + else { + prStaRec = prBowFsmInfo->prTargetStaRec; + } + + if(prStaRec) { + //cnmStaRecFree(prAdapter, prStaRec, TRUE); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + kalPrint("bowDisconnectLink\n"); + /*No one connected*/ + if (g_u4LinkCount == 0 && g_u4Beaconing != 0) + { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer); + bowStopping(prAdapter); + kalPrint("bowStopping\n"); + /*Restore TxPower from Short range mode*/ +#if CFG_SUPPORT_NVRAM && 0 + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + /*Uninit BoW Interface*/ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +bowValidateAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ) +{ + BOOLEAN fgReplyAssocResp = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T)NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAssocReq, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("bowValidateAssocReq, prAssocReqFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAssocReqFrame->aucSrcAddr[0], + prAssocReqFrame->aucSrcAddr[1], + prAssocReqFrame->aucSrcAddr[2], + prAssocReqFrame->aucSrcAddr[3], + prAssocReqFrame->aucSrcAddr[4], + prAssocReqFrame->aucSrcAddr[5])); +#endif + + /*Assoc Accept*/ + while(EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n")); +#endif + /*Update StaRec*/ + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_BOW_INDEX, + prAssocReqFrame->aucSrcAddr); + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; + +#if CFG_BOW_RATE_LIMITATION + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | + RATE_SET_BIT_48M | + RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the avaliable highest rate*/ + if(prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } else { + /*If no avaliable rate is found, DECLINE the association*/ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + + /*Undpate BssInfo to FW*/ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*reply successful*/ + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAssocResp = TRUE; + break; + } + + /*Reject Assoc*/ + if(*pu2StatusCode != STATUS_CODE_SUCCESSFUL) { + /*Reply Assoc with reject every 5s*/ + rCurrentTime = kalGetTimeTick(); + if(CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAssocTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAssocTime == 0 + ) { + fgReplyAssocResp = TRUE; + rLastRejectAssocTime = rCurrentTime; + } + } + + return fgReplyAssocResp; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +bowValidateAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PP_STA_RECORD_T pprStaRec, + OUT PUINT_16 pu2StatusCode + ) +{ + BOOLEAN fgReplyAuth = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T)NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime = 0; + + /* TODO(Kevin): Call BoW functions to check .. + 1. Check we are BoW now. + 2. Check we can accept connection from thsi peer + 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("bowValidateAuth, prAuthFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAuthFrame->aucSrcAddr[0], + prAuthFrame->aucSrcAddr[1], + prAuthFrame->aucSrcAddr[2], + prAuthFrame->aucSrcAddr[3], + prAuthFrame->aucSrcAddr[4], + prAuthFrame->aucSrcAddr[5])); +#endif + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_BOW_INDEX, + prAuthFrame->aucSrcAddr); + if (!prStaRec) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, cnmStaRecAlloc.\n")); +#endif + prStaRec = cnmStaRecAlloc(prAdapter, + (UINT_8) NETWORK_TYPE_BOW_INDEX); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + ASSERT(prStaRec); + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + prBowBssInfo->prStaRecOfAP = prStaRec; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, cnmStaRecChangeState.\n")); +#endif + } + else + { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex)); +#endif + bssRemoveStaRecFromClientList(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType)); + DBGLOG(BOW, EVENT, ("bowValidateAuth, prStaRec->ucNetTypeIndex, %x.\n", prStaRec->ucNetTypeIndex)); +#endif + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->ucJoinFailureCount = 0; + *pprStaRec = prStaRec; + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAuth = TRUE; + } + else { + cnmStaRecFree(prAdapter, prStaRec, FALSE); + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + /*Reply auth with reject every 5s*/ + rCurrentTime = kalGetTimeTick(); + if(CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAuthTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAuthTime == 0 + ) { + fgReplyAuth = TRUE; + rLastRejectAuthTime = rCurrentTime; + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth)); +#endif + return fgReplyAuth; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowRunEventChGrant ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_GRANT_T prMsgChGrant; + UINT_8 ucTokenID; + UINT_32 u4GrantInterval; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T)prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Entering bowRunEventChGrant.\n")); +#endif + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel*/ + if((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)){ +#if CFG_BOW_TEST + printk("BoW Channel [GIVE UP:%d]\n", ucTokenID); + printk("[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); +#endif + bowReleaseCh(prAdapter); + return; + } + + /* 2. channel privilege has been approved */ + prBowFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if 0 + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + prBowFsmInfo->u4ChGrantedInterval - BOW_JOIN_CH_GRANT_THRESHOLD); +#else + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + BOW_JOIN_CH_REQUEST_INTERVAL - BOW_JOIN_CH_GRANT_THRESHOLD); +#endif + + /* 3.2 set local variable to indicate join timer is ticking */ + prBowFsmInfo->fgIsInfraChannelFinished = FALSE; + +#if CFG_BOW_TEST + printk("BoW Channel [GRANTED:%d].\n", ucTokenID); +#endif + + if(eFsmState == BOW_DEVICE_STATE_ACQUIRING_CHANNEL) { + bowStarting(prAdapter); + bowReleaseCh(prAdapter); + if(prBowFsmInfo->ucRole == BOW_RESPONDER) { + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); + } + } + else { + /*update bssinfo*/ + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowReleaseCh(prAdapter); + } + + return; +} /* end of aisFsmRunEventChGrant() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM for channel privilege requesting +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowRequestCh ( + IN P_ADAPTER_T prAdapter + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_REQ_T prMsgChReq; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted == FALSE) + { + +#if CFG_BOW_TEST + printk("BoW channel [REQUEST:%d], %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq+1, prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + prMsgChReq = (P_MSG_CH_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); // Can't indicate CNM for channel acquiring + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; //prBowFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = CHNL_EXT_SCN; //prBowFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = prBowFsmInfo->eBand; //prBowFsmInfo->prTargetBssDesc->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prBowFsmInfo->aucPeerAddress); + + + prBowFsmInfo->fgIsChannelRequested = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChReq, + MSG_SEND_METHOD_BUF); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform BOW that channel privilege is granted +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowReleaseCh ( + IN P_ADAPTER_T prAdapter + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if(prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) + { +#if CFG_BOW_TEST + printk("BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + + prBowFsmInfo->fgIsChannelRequested = FALSE; + prBowFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); // Can't release Channel to CNM + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChAbort, + MSG_SEND_METHOD_BUF); + } + + return; +} /* end of aisFsmReleaseCh() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowChGrantedTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + printk("BoW Channel [TIMEOUT]\n"); +#endif +#if 1 + //bowReleaseCh(prAdapter); + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*If connecting is not completed, request CH again*/ + if((eFsmState == BOW_DEVICE_STATE_CONNECTING) || + (eFsmState == BOW_DEVICE_STATE_STARTING)) + { + bowRequestCh(prAdapter); + } +#endif +} + + +BOOLEAN +bowNotifyAllLinkDisconnected ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucBowTableIdx = 0; + CMD_INFO_T rCmdInfo; + + ASSERT(prAdapter); + + kalMemZero(&rCmdInfo, sizeof(CMD_INFO_T)); + + while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) + { + if (arBowTable[ucBowTableIdx].fgIsValid) + { + COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, arBowTable[ucBowTableIdx].aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowNotifyAllLinkDisconnected, arBowTable[%x].aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].aucPeerAddress[0], + arBowTable[ucBowTableIdx].aucPeerAddress[1], + arBowTable[ucBowTableIdx].aucPeerAddress[2], + arBowTable[ucBowTableIdx].aucPeerAddress[3], + arBowTable[ucBowTableIdx].aucPeerAddress[4], + arBowTable[ucBowTableIdx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("bowNotifyAllLinkDisconnected, arBowTable[%x].fgIsValid, %x.\n", ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid)); +#endif +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + 0, + NULL, + 0 + ); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ + +BOOLEAN +bowCheckBowTableIfVaild( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6] + ) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for(idx = 0 ; idx < CFG_BOW_PHYSICAL_LINK_NUM ; idx++) + { + if( arBowTable[idx].fgIsValid && + EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) + { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], + arBowTable[idx].aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid)); + +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return FALSE; +} + +BOOLEAN +bowGetBowTableContent( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBowTableIdx, + OUT P_BOW_TABLE_T prBowTable + ) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) + { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid)); + printk("GET State [%d]\n", arBowTable[ucBowTableIdx].eState); +#endif + prBowTable = &(arBowTable[ucBowTableIdx]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + + +BOOLEAN +bowSetBowTableContent( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBowTableIdx, + IN P_BOW_TABLE_T prBowTable + ) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + COPY_MAC_ADDR(arBowTable[ucBowTableIdx].aucPeerAddress, prBowTable->aucPeerAddress); + arBowTable[ucBowTableIdx].eState = prBowTable->eState; + arBowTable[ucBowTableIdx].fgIsValid = prBowTable->fgIsValid; + arBowTable[ucBowTableIdx].ucAcquireID = prBowTable->ucAcquireID; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, prBowTable->eState, prBowTable->aucPeerAddress); + //kalSetBowRole(prAdapter->prGlueInfo, prBowTable->ucRole, prBowTable->aucPeerAddress); + +#if CFG_BOW_TEST + printk("SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid)); +#endif + + return TRUE; + +} + + +BOOLEAN +bowGetBowTableEntryByPeerAddress( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6], + OUT PUINT_8 pucBowTableIdx + ) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for(idx = 0 ; idx < CFG_BOW_PHYSICAL_LINK_NUM ; idx++) + { + if( arBowTable[idx].fgIsValid && + EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) + { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], + arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid)); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + *pucBowTableIdx = idx; + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + + +BOOLEAN +bowGetBowTableFreeEntry( + IN P_ADAPTER_T prAdapter, + OUT PUINT_8 pucBowTableIdx + ) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for(idx = 0 ; idx < CFG_BOW_PHYSICAL_LINK_NUM ; idx++) + { + if(!arBowTable[idx].fgIsValid) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid)); +#endif + *pucBowTableIdx = idx; + arBowTable[idx].fgIsValid = TRUE; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + + +ENUM_BOW_DEVICE_STATE +bowGetBowTableState( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6] + ) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for(idx = 0 ; idx < CFG_BOW_PHYSICAL_LINK_NUM ; idx++) + { + if( arBowTable[idx].fgIsValid && + EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) + { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], + arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, ("bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid)); + DBGLOG(BOW, EVENT, ("bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState)); + printk("GET State [%d]\n", arBowTable[idx].eState); +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return arBowTable[idx].eState; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return BOW_DEVICE_STATE_DISCONNECTED; +} + + +BOOLEAN +bowSetBowTableState( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6], + IN ENUM_BOW_DEVICE_STATE eState + ) +{ + UINT_8 ucBowTableIdx; + + if(bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + arBowTable[ucBowTableIdx].eState = eState; +#if CFG_BOW_TEST + printk("SET State [%d]\n", eState); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + + +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c new file mode 100755 index 000000000000..604d793158d5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c @@ -0,0 +1,5568 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_lib.c#2 $ +*/ +/*! \file wlan_lib.c + \brief Internal driver stack will export the required procedures here for GLUE Layer. + + This file contains all routines which are exported from MediaTek 802.11 Wireless + LAN driver stack to GLUE Layer. +*/ + + +/* +** $Log: wlan_lib.c $ +** +** 08 15 2012 eason.tsai +** [ALPS00338170] [Need Patch] [Volunteer Patch] modify build warning +** fix build waring for codechange + * + * 07 13 2012 cp.wu + * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for termination after SDIO error has happened + * [driver domain] add force reset by host-to-device interrupt mechanism + * + * 06 11 2012 cp.wu + * [WCXRP00001252] [MT6620 Wi-Fi][Driver] Add debug message while encountering firmware response timeout + * output message while timeout event occurs + * + * 06 11 2012 eason.tsai + * NULL + * change from binay to hex code + * + * 06 08 2012 eason.tsai + * NULL + * Nvram context covert from 6620 to 6628 for old 6620 meta tool + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 04 2012 eason.tsai + * NULL + * modify the cal fail report code. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * correct scan result removing policy. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 11 14 2011 cm.chang + * [WCXRP00001104] [All Wi-Fi][FW] Show init process by HW mail-box register + * Show FW initial ID when timeout to wait for ready bit + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 10 18 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * when powering off, always clear pending interrupts, then wait for RDY to be de-asserted + * + * 10 14 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * shorten the packet length for firmware download if no more than 2048 bytes. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 20 2011 cp.wu + * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized + * 1. always show error message for SDIO bus errors. + * 2. reset bus error flag when re-initialization + * + * 08 26 2011 cm.chang + * [WCXRP00000952] [MT5931 Wi-Fi][FW] Handshake with BWCS before DPD/TX power calibration + * Fix compiling error for WinXP MT5931 driver + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS Sync ready for WinXP. + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 19 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * escape from normal path if any error is occured. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 24 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * if there is no valid address in chip, generate a new one from driver domain instead of firmware domain due to sufficient randomness + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 06 20 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * disable whole-chip resetting mechanism due to the need of further ECO to work as expected. + * + * 05 31 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * changed to use non-zero checking for valid bit in NVRAM content + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 18 2011 cp.wu + * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain + * pass PHY_PARAM in NVRAM from driver to firmware. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * correct assertion. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 05 11 2011 cm.chang + * [WCXRP00000717] [MT5931 Wi-Fi][Driver] Handle wrong NVRAM content about AP bandwidth setting + * . + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * change delay from 100ms to 120ms upon DE's suggestion. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 22 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * skip power-off handshaking when RESET indication is received. + * + * 04 22 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * . + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 04 15 2011 cp.wu + * [WCXRP00000654] [MT6620 Wi-Fi][Driver] Add loop termination criterion for wlanAdapterStop(). + * add loop termination criteria for wlanAdapterStop(). + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 04 06 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside wlanAdapterStart + * invoke nicReleaseAdapterMemory() as failure handling in case wlanAdapterStart() failed unexpectedly + * + * 03 29 2011 wh.su + * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error + * fixed the kclocwork error. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 02 25 2011 cp.wu + * [WCXRP00000496] [MT5931][Driver] Apply host-triggered chip reset before initializing firmware download procedures + * apply host-triggered chip reset mechanism before initializing firmware download procedures. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Chnage GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 01 2011 george.huang + * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers + * init variable for CTIA. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer when the corresponding BSS is disconnected due to beacon timeout + * remove from scanning result when the BSS is disconnected due to beacon timeout. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * while being unloaded, clear all pending interrupt then set LP-own to firmware + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 22 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Remove controling auto rate from initial setting. The initial setting is defined by FW code. + * + * 12 15 2010 cp.wu + * NULL + * sync. with ALPS code by enabling interrupt just before leaving wlanAdapterStart() + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * Change Param name for invitation connection. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 03 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) use 8 buffers for MT5931 which is equipped with less memory + * 2) modify MT5931 debug level to TRACE when download is successful + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * for MT5931, adapter initialization is done *after* firmware is downloaded. + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * correct MT5931 firmware download procedure: + * MT5931 will download firmware first then acquire LP-OWN + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) update MT5931 firmware encryption tool. (using 64-bytes unit) + * 2) update MT5931 firmware download procedure + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 25 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add option for enable/disable TX PWR gain adjustment (default: off) + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 15 2010 cp.wu + * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A + * bugfix: always reset pointer to IEbuf to zero when keeping scanning result for the connected AP + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 13 2010 cp.wu + * NULL + * acquire & release power control in oid handing wrapper. + * + * 09 09 2010 cp.wu + * NULL + * move IE to buffer head when the IE pointer is not pointed at head. + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 09 01 2010 cp.wu + * NULL + * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 13 2010 cp.wu + * NULL + * correction issue: desired phy type not initialized as ABGN mode. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 10 2010 cm.chang + * NULL + * Support EEPROM read/write in RF test mode + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 13 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Reduce unnecessary type casting + * + * 07 13 2010 cp.wu + * + * use multiple queues to keep 1x/MMPDU/CMD's strict order even when there is incoming 1x frames. + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * initialize mbox & ais_fsm in wlanAdapterStart() + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * simplify timer usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable interrupt then send power control command packet. + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when stopping adapter, wait til RDY bit has been cleaerd. + * 2) set TASK_OFFLOAD as driver-core OIDs + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * roll-back to rev.60. + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove redundant firmware image unloading + * 2) use compile-time macros to separate logic related to accquiring own + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always set fw-own before driver is unloaded. + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * 2) command sequence number is now increased atomically + * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * 2) add 2 kal API for later integration + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) eliminate unused definitions + * 2) ready bit will be polled for limited iteration + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * kalOidComplete is not necessary in linux + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use pass-in prRegInfo instead of accessing prGlueInfo directly + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding none-glue code portability + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding non-glue code portability + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve non-glue code portability + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load adress & start address are now configured from config.h + * due to the different configurations on FPGA and ASIC + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * only send CMD_NIC_POWER_CTRL in wlanAdapterStop() when card is not removed and is not in D3 state + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * +* 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when starting adapter, read local adminsitrated address from registry and send to firmware via CMD_BASIC_CONFIG. + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 03 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add command/event definitions for initial states + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for QM_TEST_MODE + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct function name .. + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * separate wlanProcesQueuePacket() into 2 APIs upon request + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct wlanAdapterStart + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * 2) firmware image length is now retrieved via NdisFileOpen + * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * 4) nicRxWaitResponse() revised + * 5) another set of TQ counter default value is added for fw-download state + * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * 2. follow MSDN defined behavior when associates to another AP + * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * wlanoidSetFrequency is now implemented by RF test command. + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * QueryRssi is no longer w/o hardware access, it is now implemented by command/event handling loop + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. clear prPendingCmdInfo properly + * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. + * + * 01 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * allow MCR read/write OIDs in RF test mode + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * 2. block TX/ordinary OID when RF test mode is engaged + * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * 4. correct some HAL implementation + * + * 01 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-12-10 16:54:36 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-12-09 20:04:59 GMT mtk02752 +** only report as connected when CFG_HIF_EMULATION_TEST is set to 1 +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-12-08 17:39:41 GMT mtk02752 +** wlanoidRftestQueryAutoTest could be executed without touching hardware +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-12-03 16:10:26 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-02 22:05:33 GMT mtk02752 +** kalOidComplete() will decrease i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-01 23:02:36 GMT mtk02752 +** remove unnecessary spinlock +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-01 22:50:38 GMT mtk02752 +** use TC4 for command, maintein i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-27 12:45:34 GMT mtk02752 +** prCmdInfo should be freed when invoking wlanReleasePendingOid() to clear pending oid +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-24 19:55:51 GMT mtk02752 +** wlanSendPacket & wlanRetransmitOfPendingFrames is only used in old data path +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-23 17:59:55 GMT mtk02752 +** clear prPendingOID inside wlanSendCommand() when the OID didn't need to be replied. +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-23 14:45:29 GMT mtk02752 +** add another version of wlanSendCommand() for command-sending only without blocking for response +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-17 22:40:44 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 10:14:56 GMT mtk01084 +** modify place to invoke wlanIst +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-10-30 18:17:07 GMT mtk01084 +** fix compiler warning +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-10-29 19:46:15 GMT mtk01084 +** invoke interrupt process routine +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-10-13 21:58:24 GMT mtk01084 +** modify for new HW architecture +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-09-09 17:26:01 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-05-20 12:21:27 GMT mtk01461 +** Add SeqNum check when process Event Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-05-19 10:38:44 GMT mtk01461 +** Add wlanReleasePendingOid() for mpReset() if there is a pending OID and no available TX resource to send it. +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-04-29 15:41:34 GMT mtk01461 +** Add handle of EVENT of CMD Result in wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-04-22 09:11:23 GMT mtk01461 +** Fix wlanSendCommand() for Driver Domain CR +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-04-21 09:33:56 GMT mtk01461 +** Update wlanSendCommand() for Driver Domain Response and handle Event Packet, wlanQuery/SetInformation() for enqueue CMD_INFO_T +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-17 20:00:08 GMT mtk01461 +** Update wlanImageSectionDownload for optimized CMD process +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-14 20:50:51 GMT mtk01426 +** Fixed compile error +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-13 16:38:40 GMT mtk01084 +** add wifi start function +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-13 14:26:44 GMT mtk01084 +** modify a parameter about FW download length +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-10 21:53:42 GMT mtk01461 +** Update wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-08 16:51:04 GMT mtk01084 +** Update for the image download part +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-01 10:32:47 GMT mtk01461 +** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-03-23 21:44:13 GMT mtk01461 +** Refine TC assignment for WmmAssoc flag +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 16:51:57 GMT mtk01084 +** modify the input argument of caller to RECLAIM_POWER_CONTROL_TO_PM() +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:27:13 GMT mtk01461 +** Add reference code of FW Image Download +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:37 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:08 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 16:28:45 GMT mtk01426 +** Init develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "mgmt/ais_fsm.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ +/* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ +const UINT_8 aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +#if QM_TEST_MODE +extern QUE_MGT_T g_rQM; +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _CODE_MAPPING_T { + UINT_32 u4RegisterValue; + INT_32 u4TxpowerOffset; +} CODE_MAPPING_T, *P_CODE_MAPPING_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +BOOLEAN fgIsBusAccessFailed = FALSE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SIGNED_EXTEND(n, _sValue) \ + (((_sValue) & BIT((n)-1)) ? ((_sValue) | BITS(n,31)) : \ + ((_sValue) & ~BITS(n,31))) + +// TODO: Check +/* OID set handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerWOHwAccess[] = { + wlanoidSetChannel, + wlanoidSetBeaconInterval, + wlanoidSetAtimWindow, + wlanoidSetFrequency, +}; + +// TODO: Check +/* OID query handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerWOHwAccess[] = { + wlanoidQueryBssid, + wlanoidQuerySsid, + wlanoidQueryInfrastructureMode, + wlanoidQueryAuthMode, + wlanoidQueryEncryptionStatus, + wlanoidQueryPmkid, + wlanoidQueryNetworkTypeInUse, + wlanoidQueryBssidList, + wlanoidQueryAcpiDevicePowerState, + wlanoidQuerySupportedRates, + wlanoidQueryDesiredRates, + wlanoidQuery802dot11PowerSaveProfile, + wlanoidQueryBeaconInterval, + wlanoidQueryAtimWindow, + wlanoidQueryFrequency, +}; + +/* OID set handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerAllowedInRFTest[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidRftestSetAutoTest, + wlanoidSetMcrWrite, + wlanoidSetEepromWrite +}; + +/* OID query handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerAllowedInRFTest[] = { + wlanoidRftestQueryAutoTest, + wlanoidQueryMcrRead, + wlanoidQueryEepromRead +} +; + +PFN_OID_HANDLER_FUNC apfnOidWOTimeoutCheck[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidSetAcpiDevicePowerState, +}; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is a private routine, which is used to check if HW access is needed +* for the OID query/ set handlers. +* +* \param[IN] pfnOidHandler Pointer to the OID handler. +* \param[IN] fgSetInfo It is a Set information handler. +* +* \retval TRUE This function needs HW access +* \retval FALSE This function does not need HW access +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanIsHandlerNeedHwAccess ( + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN BOOLEAN fgSetInfo + ) +{ + PFN_OID_HANDLER_FUNC* apfnOidHandlerWOHwAccess; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerWOHwAccess = apfnOidSetHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidSetHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } + else { + apfnOidHandlerWOHwAccess = apfnOidQueryHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidQueryHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOHwAccess[i] == pfnOidHandler) { + return FALSE; + } + } + + return TRUE; +} /* wlanIsHandlerNeedHwAccess */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set flag for later handling card +* ejected event. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +* +* \note When surprised removal happens, Glue layer should invoke this +* function to notify WPDD not to do any hw access. +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanCardEjected ( + IN P_ADAPTER_T prAdapter + ) +{ + DEBUGFUNC("wlanCardEjected"); + //INITLOG(("\n")); + + ASSERT(prAdapter); + + /* mark that the card is being ejected, NDIS will shut us down soon */ + nicTxRelease(prAdapter); + +} /* wlanCardEjected */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Create adapter object +* +* \param prAdapter This routine is call to allocate the driver software objects. +* If fails, return NULL. +* \retval NULL If it fails, NULL is returned. +* \retval NOT NULL If the adapter was initialized successfully. +*/ +/*----------------------------------------------------------------------------*/ +P_ADAPTER_T +wlanAdapterCreate ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_ADAPTER_T prAdpater = (P_ADAPTER_T)NULL; + + DEBUGFUNC("wlanAdapterCreate"); + + do { + prAdpater = (P_ADAPTER_T) kalMemAlloc(sizeof(ADAPTER_T), VIR_MEM_TYPE); + + if (!prAdpater) { + DBGLOG(INIT, ERROR, ("Allocate ADAPTER memory ==> FAILED\n")); + break; + } + +#if QM_TEST_MODE + g_rQM.prAdapter = prAdpater; +#endif + kalMemZero(prAdpater, sizeof(ADAPTER_T)); + prAdpater->prGlueInfo = prGlueInfo; + + } while(FALSE); + + return prAdpater; +} /* wlanAdapterCreate */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroy adapter object +* +* \param prAdapter This routine is call to destroy the driver software objects. +* If fails, return NULL. +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanAdapterDestroy ( + IN P_ADAPTER_T prAdapter + ) +{ + + if (!prAdapter) { + return; + } + + kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(ADAPTER_T)); + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize the adapter. The sequence is +* 1. Disable interrupt +* 2. Read adapter configuration from EEPROM and registry, verify chip ID. +* 3. Create NIC Tx/Rx resource. +* 4. Initialize the chip +* 5. Initialize the protocol +* 6. Enable Interrupt +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAdapterStart ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, + IN PVOID pvFwImageMapFile, + IN UINT_32 u4FwImageFileLength + ) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 i, u4Value = 0; + UINT_32 u4WHISR = 0; + UINT_8 aucTxCount[8]; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwLoadAddr, u4ImgSecSize; + #if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); + #endif +#endif +#if (defined(MT5931) && (!CFG_SUPPORT_BCM_BWCS)) + PARAM_PTA_IPC_T rBwcsPta; + UINT_32 u4SetInfoLen; +#endif + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + //4 <0> Reset variables in ADAPTER_T + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + //4 <0.1> reset fgIsBusAccessFailed + fgIsBusAccessFailed = FALSE; + + do { + if ( (u4Status = nicAllocateAdapterMemory(prAdapter)) != WLAN_STATUS_SUCCESS ) { + DBGLOG(INIT, ERROR, ("nicAllocateAdapterMemory Error!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + +#if defined(MT6620) || defined(MT6628) + DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Acquiring LP-OWN\n")); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + #if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); + #endif + + if(prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, ("nicpmSetDriverOwn() failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + //4 <1> Initialize the Adapter + if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) { + DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + //4 <2> Initialize System Service (MGMT Memory pool and STA_REC) + nicInitSystemService(prAdapter); + + //4 <3> Initialize Tx + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + //4 <4> Initialize Rx + nicRxInitialize(prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD + #if defined(MT6620) || defined(MT6628) + if (pvFwImageMapFile) { + /* 1. disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3. FW download here */ + u4FwLoadAddr = prRegInfo->u4LoadAddress; + + #if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + // 3a. parse file header for decision of divided firmware download or not + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T)pvFwImageMapFile; + + if(prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8)pvFwImageMapFile + u4CRCOffset, u4FwImageFileLength - u4CRCOffset)) { + fgValidHead = TRUE; + } + else { + fgValidHead = FALSE; + } + + /* 3b. engage divided firmware downloading */ + if(fgValidHead == TRUE) { + for(i = 0 ; i < prFwHead->u4NumOfEntries ; i++) { + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if(wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8)pvFwImageMapFile + prFwHead->arSection[i].u4Offset) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + } + #else + for(j = 0 ; j < prFwHead->arSection[i].u4Length ; j += CMD_PKT_SIZE_FOR_IMAGE) { + if(j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + if(wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + prFwHead->arSection[i].u4Offset + j) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + #endif + + /* escape from loop if any pending error occurs */ + if(u4Status == WLAN_STATUS_FAILURE) { + break; + } + } + } + else + #endif + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if(wlanImageSectionDownloadAggregated(prAdapter, + u4FwLoadAddr, + u4FwImageFileLength, + (PUINT_8)pvFwImageMapFile) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + } + #else + for (i = 0; i < u4FwImageFileLength ; i += CMD_PKT_SIZE_FOR_IMAGE) { + if(i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImageFileLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImageFileLength - i; + + if(wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + #endif + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + #if !CFG_ENABLE_FW_DOWNLOAD_ACK + // Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response + if(wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + #endif + } + else { + DBGLOG(INIT, ERROR, ("No Firmware found!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 4. send Wi-Fi Start command */ + #if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, + TRUE, + prRegInfo->u4StartAddress); + #else + wlanConfigWifiFunc(prAdapter, + FALSE, + 0); + #endif + #elif defined(MT5931) + if (pvFwImageMapFile) { + DBGLOG(INIT, TRACE, ("Download Address: 0x%08X\n", prRegInfo->u4LoadAddress)); + DBGLOG(INIT, TRACE, ("Firmware Length: 0x%08X\n", u4FwImageFileLength)); + + do { +#if CFG_SUPPORT_WHOLE_CHIP_RESET +#define RESET_RDY_INTERVAL (120) + + /* 1.0 whole-chip reset except HIFSYS */ + HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_CHIP_RST); + HAL_MCR_WR(prAdapter, MCR_WMCSR, 0); + + /* 1.0.1 delay for EEIF ready */ + kalMsleep(RESET_RDY_INTERVAL); +#endif + + /* 1.1 wait for INIT_RDY */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_INI_RDY) { + DBGLOG(INIT, TRACE, ("INIT-RDY detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for Init Ready bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* 1.2 set KSEL/FLEN */ + HAL_MCR_WR(prAdapter, MCR_FWCFG, u4FwImageFileLength >> 6); + + /* 1.3 enable FWDL_EN */ + HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_FWDLEN); + + /* 1.4 wait for PLL_RDY */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_PLLRDY) { + DBGLOG(INIT, TRACE, ("PLL-RDY detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for PLL Ready bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* 2.1 turn on HIFSYS firmware download mode */ + HAL_MCR_WR(prAdapter, MCR_FWDLSR, FWDLSR_FWDL_MODE); + + /* 2.2 set starting address */ + u4FwLoadAddr = prRegInfo->u4LoadAddress; + HAL_MCR_WR(prAdapter, MCR_FWDLDSAR, u4FwLoadAddr); + + /* 3. upload firmware */ + for (i = 0; i < u4FwImageFileLength ; i += CMD_PKT_SIZE_FOR_IMAGE) { + if(i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImageFileLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImageFileLength - i; + + if(wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* 4.1 poll FWDL_OK & FWDL_FAIL bits */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_DL_OK) { + DBGLOG(INIT, TRACE, ("DL_OK detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || (u4Value & WMCSR_DL_FAIL)) { + DBGLOG(INIT, ERROR, ("DL_FAIL detected: 0x%08X\n", u4Value)); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for DL_OK/DL_FAIL bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* 4.2 turn off HIFSYS download mode */ + HAL_MCR_WR(prAdapter, MCR_FWDLSR, 0); + + } while (FALSE); + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* 5. disable interrupt */ + nicDisableInterrupt(prAdapter); + } + else { + DBGLOG(INIT, ERROR, ("No Firmware found!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + #endif +#endif + + DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Waiting for Ready bit..\n")); + //4 <5> check Wi-Fi FW asserts ready bit + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(INIT, TRACE, ("Ready bit asserted\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(INIT, ERROR, ("Waiting for Ready bit: Timeout, ID=%d\n", + (u4MailBox0 & 0x0000FFFF))); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + +#if defined(MT5931) + // Acquire LP-OWN + DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Acquiring LP-OWN\n")); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + #if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); + #endif + + if(prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, ("nicpmSetDriverOwn() failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + //4 <1> Initialize the Adapter + if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) { + DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* post initialization for MT5931 due to some CR is only accessible after driver own */ + nicRxPostInitialize(prAdapter); +#endif + + if(u4Status == WLAN_STATUS_SUCCESS) { + // 1. reset interrupt status + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if(HAL_IS_TX_DONE_INTR(u4WHISR)) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + } + + /* 2. reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + +#if CFG_SUPPORT_OSC_SETTING && defined(MT5931) + wlanSetMcuOscStableTime(prAdapter, 0); +#endif + + /* 3. query for permanent address by polling */ + wlanQueryPermanentAddress(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + /* 4. query for NIC capability */ + wlanQueryNicCapability(prAdapter); +#endif + + /* 5. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6. indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + if(u4Status != WLAN_STATUS_SUCCESS) { + break; + } + + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC)wlanReleasePendingOid, + (UINT_32)NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + + /* Online scan option */ + if(prRegInfo->fgDisOnlineScan == 0) { + prAdapter->fgEnOnlineScan = TRUE; + } + else { + prAdapter->fgEnOnlineScan = FALSE; + } + + /* Beacon lost detection option */ + if(prRegInfo->fgDisBcnLostDetection != 0) { + prAdapter->fgDisBcnLostDetection = TRUE; + } + + /* Load compile time constant */ + prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; + prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; + +#if 1// set PM parameters + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; + + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; + + DBGLOG(INIT, TRACE, ("[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, + prAdapter->u4UapsdAcBmp, + prAdapter->u4MaxSpLen)); + + prAdapter->fgEnCtiaPowerMode = FALSE; + +#endif + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, prRegInfo); + + /* Enable WZC Disassociation */ + prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; + + /* Apply Rate Setting */ + if((ENUM_REGISTRY_FIXED_RATE_T)(prRegInfo->u4FixedRate) < FIXED_RATE_NUM) { + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T)(prRegInfo->u4FixedRate); + } + else { + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + } + + if(prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) { + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + } + else if((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) { + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + } + else { + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + } + + /* Disable Hidden SSID Join */ + prAdapter->rWifiVar.fgEnableJoinToHiddenSSID = FALSE; + + /* Enable Short Slot Time */ + prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable = TRUE; + + /* configure available PHY type set */ + nicSetAvailablePhyTypeSet(prAdapter); + +#if 1// set PM parameters + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + {/*CR:WCNAE00007101*/ + struct net_device *prDev = prAdapter->prGlueInfo->prDevHandler; + + if (prDev != NULL) { + glBusSetIrq(prDev, NULL, prAdapter->prGlueInfo ); + } + else { + printk(KERN_INFO "Skip glBusSetIrq because of the prDev\n"); + } + } + nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_AIS_INDEX, //FIXIT + prAdapter->u4PowerMode, + FALSE); + } + +#endif + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + wlanLoadManufactureData(prAdapter, prRegInfo); +#endif + +#if (defined(MT5931) && (!CFG_SUPPORT_BCM_BWCS)) + //Enable DPD calibration. + rBwcsPta.u.aucBTPParams[0] = 0x00; + rBwcsPta.u.aucBTPParams[1] = 0x01; + rBwcsPta.u.aucBTPParams[2] = 0x00; + rBwcsPta.u.aucBTPParams[3] = 0x80; + + wlanoidSetBT(prAdapter, + (PVOID)&rBwcsPta, + sizeof(PARAM_PTA_IPC_T), + &u4SetInfoLen); +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, + prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, + prRegInfo->u4ArSysParam2, + prRegInfo->u4ArSysParam3); +#endif + + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + /* clock gating workaround */ + prAdapter->fgIsClockGatingEnabled = FALSE; +#endif + + } while(FALSE); + + if(u4Status == WLAN_STATUS_SUCCESS) { + // restore to hardware default + HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); + HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); + + /* Enable interrupt */ + nicEnableInterrupt(prAdapter); + + } + else { + // release allocated memory + nicReleaseAdapterMemory(prAdapter); + } + + return u4Status; +} /* wlanAdapterStart */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Uninitialize the adapter +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAdapterStop ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i, u4Value = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == TRUE) { + nicDisableClockGating(prAdapter); + } +#endif + + /* MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + if(prAdapter->rAcpiState == ACPI_STATE_D0 && +#if (CFG_CHIP_RESET_SUPPORT == 1) + kalIsResetting() == FALSE && +#endif + kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + + /* 0. Disable interrupt, this can be done without Driver own */ + nicDisableInterrupt(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* 1. Set CMD to FW to tell WIFI to stop (enter power off state) */ + if(prAdapter->fgIsFwOwn == FALSE && + wlanSendNicPowerCtrlCmd(prAdapter, 1) == WLAN_STATUS_SUCCESS) { + /* 2. Clear pending interrupt */ + i = 0; + while(i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 3. Wait til RDY bit has been cleaerd */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if ((u4Value & WCIR_WLAN_READY) == 0) + break; + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || i >= CFG_RESPONSE_POLLING_TIMEOUT) { + break; + } + else { + i++; + kalMsleep(10); + } + } + } + + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + +#if CFG_FORCE_RESET_UNDER_BUS_ERROR + if(HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == TRUE) { + /* force acquire firmware own */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + + /* delay for 10ms */ + kalMdelay(10); + + /* force firmware reset via software interrupt */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WSICR, WSICR_H2D_SW_INT_SET); + + /* force release firmware own */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + } +#endif + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } + + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + nicReleaseAdapterMemory(prAdapter); + +#if defined(_HIF_SPI) + /* Note: restore the SPI Mode Select from 32 bit to default */ + nicRestoreSpiDefMode(prAdapter); +#endif + + return u4Status; +} /* wlanAdapterStop */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by ISR (interrupt). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval TRUE: NIC's interrupt +* \retval FALSE: Not NIC's interrupt +*/ +/*----------------------------------------------------------------------------*/ +BOOL +wlanISR ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgGlobalIntrCtrl + ) +{ + ASSERT(prAdapter); + + if (fgGlobalIntrCtrl) { + nicDisableInterrupt(prAdapter); + + //wlanIST(prAdapter); + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by IST (task_let). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanIST ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + nicProcessIST(prAdapter); + + nicEnableInterrupt(prAdapter); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check command queue to find out if any could be dequeued +* and/or send to HIF to MT6620 +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdQue Pointer of Command Queue (in Glue Layer) +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanProcessCommandQueue ( + IN P_ADAPTER_T prAdapter, + IN P_QUE_T prCmdQue + ) +{ + WLAN_STATUS rStatus; + QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdQue); + + prTempCmdQue = &rTempCmdQue; + prMergeCmdQue = &rMergeCmdQue; + prStandInCmdQue = &rStandInCmdQue; + + QUEUE_INITIALIZE(prTempCmdQue); + QUEUE_INITIALIZE(prMergeCmdQue); + QUEUE_INITIALIZE(prStandInCmdQue); + + //4 <1> Move whole list of CMD_INFO to temp queue + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + //4 <2> Dequeue from head and check it is able to be sent + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while(prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + switch(prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + /* command packet will be always sent */ + eFrameAction = FRAME_ACTION_TX_PKT; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* inquire with QM */ + eFrameAction = qmGetFrameAction(prAdapter, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, + NULL, + FRAME_TYPE_802_1X); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = (P_MSDU_INFO_T)(prCmdInfo->prPacket); + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucNetworkType, + prMsduInfo->ucStaRecIndex, + prMsduInfo, + FRAME_TYPE_MMPDU); + break; + + default: + ASSERT(0); + break; + } + + //4 <3> handling upon dequeue result + if(eFrameAction == FRAME_ACTION_DROP_PKT) { + wlanReleaseCommand(prAdapter, prCmdInfo); + } + else if(eFrameAction == FRAME_ACTION_QUEUE_PKT) { + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } + else if(eFrameAction == FRAME_ACTION_TX_PKT) { + //4 <4> Send the command + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if(rStatus == WLAN_STATUS_RESOURCES) { + // no more TC4 resource for further transmission + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + break; + } + else if(rStatus == WLAN_STATUS_PENDING) { + // command packet which needs further handling upon response + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), prQueueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } + else { + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (rStatus == WLAN_STATUS_SUCCESS) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); + } + } + else { + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, rStatus); + } + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } + else { + ASSERT(0); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + //4 <3> Merge back to original queue + //4 <3.1> Merge prMergeCmdQue & prTempCmdQue + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prTempCmdQue); + + //4 <3.2> Move prCmdQue to prStandInQue, due to prCmdQue might differ due to incoming 802.1X frames + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prStandInCmdQue, prCmdQue); + + //4 <3.3> concatenate prStandInQue to prMergeCmdQue + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prStandInCmdQue); + + //4 <3.4> then move prMergeCmdQue to prCmdQue + QUEUE_MOVE_ALL(prCmdQue, prMergeCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some informations of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendCommand ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + //DbgPrint("wlanSendCommand()\n"); + // + // +#if DBG && 0 + LOG_FUNC("wlanSendCommand()\n"); + LOG_FUNC("CmdType %u NetworkType %u StaRecIndex %u Oid %u CID 0x%x SetQuery %u NeedResp %u CmdSeqNum %u\n", + prCmdInfo->eCmdType, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, + prCmdInfo->fgIsOid, + prCmdInfo->ucCID, + prCmdInfo->fgSetQuery, + prCmdInfo->fgNeedResp, + prCmdInfo->ucCmdSeqNum); +#endif + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == TRUE) { + nicDisableClockGating(prAdapter); + } +#endif + + do { + // <0> card removal check + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + + // <1> Normal case of sending CMD Packet + if (!prCmdInfo->fgDriverDomainMCR) { + // <1.1> Assign Traffic Class(TC) = TC4. + ucTC = TC4_INDEX; + + // <1.2> Check if pending packet or resource was exhausted + if ((rStatus = nicTxAcquireResource(prAdapter, ucTC)) == WLAN_STATUS_RESOURCES) { + DbgPrint("NO Resource:%d\n", ucTC); + break; + } + + // <1.3> Forward CMD_INFO_T to NIC Layer + rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); + + // <1.4> Set Pending in response to Query Command/Need Response + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + rStatus = WLAN_STATUS_PENDING; + } + } + } + // <2> Special case for access Driver Domain MCR + else { + P_CMD_ACCESS_REG prCmdAccessReg; + prCmdAccessReg = (P_CMD_ACCESS_REG)(prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); + + if (prCmdInfo->fgSetQuery) { + HAL_MCR_WR(prAdapter, + (prCmdAccessReg->u4Address & BITS(2,31)), //address is in DWORD unit + prCmdAccessReg->u4Data); + } + else { + P_CMD_ACCESS_REG prEventAccessReg; + UINT_32 u4Address; + + u4Address = prCmdAccessReg->u4Address; + prEventAccessReg = (P_CMD_ACCESS_REG)prCmdInfo->pucInfoBuffer; + prEventAccessReg->u4Address = u4Address; + + HAL_MCR_RD(prAdapter, + prEventAccessReg->u4Address & BITS(2,31), //address is in DWORD unit + &prEventAccessReg->u4Data); + } + } + + } + while (FALSE); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == FALSE) { + nicEnableClockGating(prAdapter); + } +#endif + + return rStatus; +} /* end of wlanSendCommand() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will release thd CMD_INFO upon its attribution + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of CMD_INFO_T + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID +wlanReleaseCommand ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + switch(prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, + WLAN_STATUS_FAILURE); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket; + + /* invoke callbacks */ + if(prMsduInfo->pfTxDoneHandler != NULL) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + } + + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + +} /* end of wlanReleaseCommand() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending OID and +* compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanReleasePendingOid ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Data + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReleasePendingOid"); + + ASSERT(prAdapter); + + DBGLOG(INIT, ERROR, ("OID Timeout! Releasing pending OIDs ..\n")); + + do { + // 1: Clear Pending OID in prAdapter->rPendingCmdQueue + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (prCmdInfo->fgIsOid) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } + else + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + // 2: Clear pending OID in glue layer command queue + kalOidCmdClearance(prAdapter->prGlueInfo); + + // 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID set + kalOidClearance(prAdapter->prGlueInfo); + + } while(FALSE); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending CMD/OID for specific +* NETWORK TYPE and compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanReleasePendingCMDbyNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + do { + // 1: Clear Pending OID in prAdapter->rPendingCmdQueue + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + DBGLOG(P2P, TRACE, ("Pending CMD for Network Type:%d \n", prCmdInfo->eNetworkType)); + + if (prCmdInfo->eNetworkType == eNetworkType) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } + else + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + + } while(FALSE); + + return; +} /* wlanReleasePendingCMDbyNetwork */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanReturnPacket ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvPacket + ) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReturnPacket"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + if (pvPacket) { + kalPacketFree(prAdapter->prGlueInfo, pvPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT, 1); +#if CFG_NATIVE_802_11 + if (GLUE_TEST_FLAG(prAdapter->prGlueInfo, GLUE_FLAG_HALT)) { + } +#endif + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (!prSwRfb){ + ASSERT(0); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)){ + ASSERT(0); + return; + } + nicRxReturnRFB(prAdapter, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that returns information about +* the capabilities and status of the driver and/or its network adapter. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] pfnOidQryHandler Function pointer for the OID query handler. +* \param[IN] pvInfoBuf Points to a buffer for return the query information. +* \param[IN] u4QueryBufferLen Specifies the number of bytes at pvInfoBuf. +* \param[OUT] pu4QueryInfoLen Points to the number of bytes it written or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryInformation ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + OUT PUINT_32 pu4QryInfoLen + ) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QryInfoLen); + + // ignore any OID request after connected, under PS current measurement mode + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { + return WLAN_STATUS_SUCCESS; // note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ?? + } + +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if(prAdapter->fgWiFiInSleepyState == TRUE) { + prAdapter->fgWiFiInSleepyState = FALSE; + } + + status = pfnOidQryHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } + else { + status = pfnOidQryHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4QryInfoLen); + } +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that allows bound protocol drivers, +* or NDIS, to request changes in the state information that the miniport +* maintains for particular object identifiers, such as changes in multicast +* addresses. +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* \param[IN] pfnOidSetHandler Points to the OID set handlers. +* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. +* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. +* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSetInformation ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + // ignore any OID request after connected, under PS current measurement mode + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { + return WLAN_STATUS_SUCCESS; // note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ?? + } + +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control by itself + */ + status = pfnOidSetHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if(prAdapter->fgWiFiInSleepyState == TRUE) { + prAdapter->fgWiFiInSleepyState = FALSE; + } + + status = pfnOidSetHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } + else { + status = pfnOidSetHandler(prAdapter, + pvInfoBuf, + u4InfoBufLen, + pu4SetInfoLen); + } +#endif + + return status; +} + + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a used to query driver's config wapi mode or not +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* +* \retval TRUE for use wapi mode +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanQueryWapiMode ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return prAdapter->rWifiVar.rConnSettings.fgWapiMode; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to Promiscuous Mode. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPromiscuousMode ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnablePromiscuousMode + ) +{ + ASSERT(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to allow to receive +* broadcast address packets. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanRxSetBroadcast ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnableBroadcast + ) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to send out CMD_NIC_POWER_CTRL command packet +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] ucPowerMode refer to CMD/EVENT document +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendNicPowerCtrlCmd ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPowerMode + ) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + /* 1. Prepare CMD */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + /* 2.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, ("ucCmdSeqNum =%d\n", ucCmdSeqNum)); + + /* 2.2 Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + kalMemZero(prWifiCmd->aucBuffer, sizeof(CMD_NIC_POWER_CTRL)); + ((P_CMD_NIC_POWER_CTRL)(prWifiCmd->aucBuffer))->ucPowerMode = ucPowerMode; + + /* 3. Issue CMD for entering specific power mode */ + ucTC = TC4_INDEX; + + while(1) { + // 3.0 Removal check + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + status = WLAN_STATUS_FAILURE; + break; + } + + // 3.1 Acquire TX Resource + if (nicTxAcquireResource(prAdapter, ucTC) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n")); + status = WLAN_STATUS_FAILURE; + break; + } + else { + continue; + } + } + + // 3.2 Send CMD Info Packet + if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR,("Fail to transmit CMD_NIC_POWER_CTRL command\n")); + status = WLAN_STATUS_FAILURE; + } + + break; + }; + + // 4. Free CMD Info Packet. + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + // 5. Add flag + if(ucPowerMode == 1) { + prAdapter->fgIsEnterD3ReqIssued = TRUE; + } + + return status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to check if it is RF test mode and +* the OID is allowed to be called or not +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanIsHandlerAllowedInRFTest ( + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN BOOLEAN fgSetInfo + ) +{ + PFN_OID_HANDLER_FUNC* apfnOidHandlerAllowedInRFTest; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } + else { + apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) { + return TRUE; + } + } + + return FALSE; +} + +#if CFG_ENABLE_FW_DOWNLOAD + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image in an aggregated way +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownloadAggregated ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, + IN UINT_32 u4ImgSecSize, + IN PUINT_8 pucImgSecBuf + ) +{ + #if defined(MT6620) || defined(MT6628) + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4PktCnt, u4Offset, u4Length; + UINT_32 u4TotalLength; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + + pucOutputBuf = prAdapter->rTxCtrl.pucTxCoalescingBufPtr; + + DEBUGFUNC("wlanImageSectionDownloadAggregated"); + + if (u4ImgSecSize == 0) { + return WLAN_STATUS_SUCCESS; + } + + // 1. Allocate CMD Info Packet and Pre-fill Headers + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + CMD_PKT_SIZE_FOR_IMAGE); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + CMD_PKT_SIZE_FOR_IMAGE; + + // 2. Use TC0's resource to download image. (only TC0 is allowed) + ucTC = TC0_INDEX; + + // 3. Setup common CMD Info Packet + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T)(prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->ucEtherTypeOffset = 0; + prInitHifTxHeader->ucCSflags = 0; + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + + // 4. Setup CMD_DOWNLOAD_BUF + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF)(prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4DataMode = 0 + #if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE + #endif + ; + + // 5.0 reset loop control variable + u4TotalLength = 0; + u4Offset = u4PktCnt = 0; + + // 5.1 main loop for maximize transmission count per access + while(u4Offset < u4ImgSecSize) { + if(nicTxAcquireResource(prAdapter, ucTC) == WLAN_STATUS_SUCCESS) { + // 5.1.1 calculate u4Length + if(u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4ImgSecSize) { + u4Length = CMD_PKT_SIZE_FOR_IMAGE; + } + else { + u4Length = u4ImgSecSize - u4Offset; + } + + // 5.1.1 increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + // 5.1.2 update HIF TX hardware header + prInitHifTxHeader->u2TxByteCount = ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16)u4Length); + + // 5.1.3 fill command header + prInitCmdDownloadBuf->u4Address = u4DestAddr + u4Offset; + prInitCmdDownloadBuf->u4Length = u4Length; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf + u4Offset, u4Length); + + // 5.1.4.1 copy header to coalescing buffer + kalMemCopy(pucOutputBuf + u4TotalLength, + (PVOID)prCmdInfo->pucInfoBuffer, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF)); + + // 5.1.4.2 copy payload to coalescing buffer + kalMemCopy(pucOutputBuf + u4TotalLength + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF), + pucImgSecBuf + u4Offset, + u4Length); + + // 5.1.4.3 update length and other variables + u4TotalLength += ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4Length); + u4Offset += u4Length; + u4PktCnt++; + + if(u4Offset < u4ImgSecSize) { + continue; + } + } + else if(u4PktCnt == 0) { + /* no resource, so get some back */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n")); + break; + } + } + + if(u4PktCnt != 0) { + // start transmission + HAL_WRITE_TX_PORT(prAdapter, + 0, + u4TotalLength, + (PUINT_8)pucOutputBuf, + prAdapter->u4CoalescingBufCachedSize); + + // reset varaibles + u4PktCnt = 0; + u4TotalLength = 0; + } + } + + // 8. Free CMD Info Packet. + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; + + #else + #error "Only MT6620/MT6628 supports firmware download in an aggregated way" + + return WLAN_STATUS_FAILURE; + + #endif +} + + #endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownload ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, + IN UINT_32 u4ImgSecSize, + IN PUINT_8 pucImgSecBuf + ) +{ + #if defined(MT6620) || defined(MT6628) + + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + + if (u4ImgSecSize == 0) { + return WLAN_STATUS_SUCCESS; + } + + // 1. Allocate CMD Info Packet and its Buffer. + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16)u4ImgSecSize; + + // 2. Use TC0's resource to download image. (only TC0 is allowed) + ucTC = TC0_INDEX; + + // 3. increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // 4. Setup common CMD Info Packet + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T)(prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + // 5. Setup CMD_DOWNLOAD_BUF + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF)(prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4Address = u4DestAddr; + prInitCmdDownloadBuf->u4Length = u4ImgSecSize; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf, u4ImgSecSize); + prInitCmdDownloadBuf->u4DataMode = 0 + #if CFG_ENABLE_FW_DOWNLOAD_ACK + | DOWNLOAD_BUF_ACK_OPTION // ACK needed + #endif + #if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE + #endif + ; + kalMemCopy(prInitCmdDownloadBuf->aucBuffer, pucImgSecBuf, u4ImgSecSize); + + // 6. Send FW_Download command + while(1) { + // 6.1 Acquire TX Resource + if (nicTxAcquireResource(prAdapter, ucTC) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n")); + break; + } + else { + continue; + } + } + + // 6.2 Send CMD Info Packet + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to transmit image download command\n")); + } + + break; + }; + + #if CFG_ENABLE_FW_DOWNLOAD_ACK + // 7. Wait for INIT_EVENT_ID_CMD_RESULT + u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); + #endif + + // 8. Free CMD Info Packet. + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; + + #elif defined(MT5931) + + UINT_32 i, u4Value; + P_HIF_HW_TX_HEADER_T prHifTxHeader; + + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + DBGLOG(INIT, TRACE, ("Destination: 0x%08X / Length: 0x%08X\n", u4DestAddr, u4ImgSecSize)); + + if (u4ImgSecSize == 0) { + return WLAN_STATUS_SUCCESS; + } + + // 1. Use TX coalescing buffer + prHifTxHeader = (P_HIF_HW_TX_HEADER_T) prAdapter->pucCoalescingBufCached; + + // 2. Setup HIF_TX_HEADER + prHifTxHeader->u2TxByteCount = (UINT_16)(ALIGN_4(sizeof(HIF_HW_TX_HEADER_T) + u4ImgSecSize)); + prHifTxHeader->ucEtherTypeOffset = 0; + prHifTxHeader->ucCSflags = 0; + + // 3. Copy payload + kalMemCopy(prHifTxHeader->aucBuffer, pucImgSecBuf, u4ImgSecSize); + + // 3.1 add 4-bytes zero tail + kalMemZero(&(prHifTxHeader->aucBuffer[ALIGN_4(u4ImgSecSize)]), sizeof(HIF_HW_TX_HEADER_T)); + + // 4. Poll til FWDL_RDY = 1 + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_FWDLSR, &u4Value); + + if (u4Value & FWDLSR_FWDL_RDY) { + DBGLOG(INIT, TRACE, ("FWDL_RDY detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for FWDL_RDY: Timeout (0x%08X)\n", u4Value)); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + // 5. Send firmware + HAL_PORT_WR(prAdapter, + MCR_FWDLDR, + prHifTxHeader->u2TxByteCount, + (PUINT_8)prHifTxHeader, + prAdapter->u4CoalescingBufCachedSize); + + return u4Status; + + #endif +} + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm previously firmware download is done without error +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageQueryStatus( + IN P_ADAPTER_T prAdapter + ) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR)]; + UINT_32 u4RxPktLength; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_PENDING_ERROR prEventPendingError; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImageQueryStatus"); + + // 1. Allocate CMD Info Packet and it Buffer. + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo, sizeof(INIT_HIF_TX_HEADER_T)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); + + // 2. Use TC0's resource to download image. (only TC0 is allowed) + ucTC = TC0_INDEX; + + // 3. increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // 4. Setup common CMD Info Packet + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T)(prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + // 5. Send command + while(1) { + // 5.1 Acquire TX Resource + if (nicTxAcquireResource(prAdapter, ucTC) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n")); + break; + } + else { + continue; + } + } + + // 5.2 Send CMD Info Packet + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to transmit image download command\n")); + } + + break; + }; + + // 6. Wait for INIT_EVENT_ID_PENDING_ERROR + do { + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("Bus error(%d)/Card removed(%d)\n", fgIsBusAccessFailed, kalIsCardRemoved(prAdapter->prGlueInfo))); + } + else if(nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("No RX response\n")); + } + else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + // EID / SeqNum check + if(prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("EVENT-ID Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucEID)); + } + else if(prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("SEQ-NUM Mismatch: %d (expected: %d)\n", prInitHifRxHeader->rInitWifiEvent.ucSeqNum, ucCmdSeqNum)); + } + else { + prEventPendingError = (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if(prEventPendingError->ucStatus != 0) { // 0 for download success + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("ERROR CODE: %d\n", prEventCmdResult->ucStatus)); + } + else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + // 7. Free CMD Info Packet. + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm the status of +* previously downloaded firmware scatter +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownloadStatus ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCmdSeqNum + ) +{ + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_CMD_RESULT prEventCmdResult; + UINT_32 u4RxPktLength; + WLAN_STATUS u4Status; + + ASSERT(prAdapter); + + do { + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("Bus error(%d)/Card removed(%d)\n", fgIsBusAccessFailed, kalIsCardRemoved(prAdapter->prGlueInfo))); + } + else if(nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("No RX response\n")); + } + else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + // EID / SeqNum check + if(prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("EVENT-ID Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucEID)); + } + else if(prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("SEQ-NUM Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucSeqNum)); + } + else { + prEventCmdResult = (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if(prEventCmdResult->ucStatus != 0) { // 0 for download success + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, ("ERROR CODE: %d\n", prEventCmdResult->ucStatus)); + } + else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + return u4Status; +} + + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to start FW normal operation. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanConfigWifiFunc ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnable, + IN UINT_32 u4StartAddress + ) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_START prInitCmdWifiStart; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanConfigWifiFunc"); + + // 1. Allocate CMD Info Packet and its Buffer. + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); + + // 2. Always use TC0 + ucTC = TC0_INDEX; + + // 3. increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // 4. Setup common CMD Info Packet + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T)(prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_START)(prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = (fgEnable == TRUE ? 1 : 0); + prInitCmdWifiStart->u4Address = u4StartAddress; + + // 5. Seend WIFI start command + while(1) { + // 5.1 Acquire TX Resource + if (nicTxAcquireResource(prAdapter, ucTC) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n")); + break; + } + else { + continue; + } + } + + // 5.2 Send CMD Info Packet + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR,("Fail to transmit WIFI start command\n")); + } + + break; + }; + + // 6. Free CMD Info Packet. + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate CRC32 checksum +* +* @param buf Pointer to the data. +* @param len data length +* +* @return crc32 value +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanCRC32( + PUINT_8 buf, + UINT_32 len) +{ + UINT_32 i, crc32 = 0xFFFFFFFF; + const UINT_32 crc32_ccitt_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d }; + + for (i = 0; i < len; i++) + crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); + + return ( ~crc32 ); +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to process queued RX packets +* +* @param prAdapter Pointer to the Adapter structure. +* prSwRfbListHead Pointer to head of RX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanProcessQueuedSwRfb ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfbListHead + ) +{ + P_SW_RFB_T prSwRfb, prNextSwRfb; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + ASSERT(prSwRfbListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prSwRfb = prSwRfbListHead; + + do { + // save next first + prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prSwRfb); + + switch(prSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_FORWARD: + nicRxProcessForwardPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_HOST_WITH_FORWARD: + nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_NULL: + nicRxReturnRFB(prAdapter, prSwRfb); + break; + + default: + break; + } + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4DequeuedCnt++; +#endif + prSwRfb = prNextSwRfb; + } while(prSwRfb); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to purge queued TX packets +* by indicating failure to OS and returned to free list +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfoListHead Pointer to head of TX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanProcessQueuedMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the OID handler needs timeout +* +* @param prAdapter Pointer to the Adapter structure. +* pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanoidTimeoutCheck ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler + ) +{ + PFN_OID_HANDLER_FUNC* apfnOidHandlerWOTimeoutCheck; + UINT_32 i; + UINT_32 u4NumOfElem; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) { + return FALSE; + } + } + + // set timer if need timeout check + //cnmTimerStartTimer(prAdapter, + // &(prAdapter->rOidTimeoutTimer), + // 1000); + cnmTimerStartTimer(prAdapter, + &(prAdapter->rOidTimeoutTimer), + 2000); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to clear any pending OID timeout check +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanoidClearTimeoutCheck ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to set up the MCUSYS's OSC stable time +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ + +#if CFG_SUPPORT_OSC_SETTING && defined(MT5931) +WLAN_STATUS +wlanSetMcuOscStableTime ( + IN P_ADAPTER_T prAdapter, + IN UINT_16 u2OscStableTime + ) +{ + UINT_8 ucCmdSeqNum = 0; + P_CMD_INFO_T prCmdInfo = NULL; + P_WIFI_CMD_T prWifiCmd = NULL; + P_CMD_MCU_LP_PARAM_T prMcuSetOscCmd = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + CMD_HDR_SIZE + sizeof(CMD_MCU_LP_PARAM_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_MCU_LP_PARAM_T cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_MCU_LP_PARAM_T); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_SET_OSC; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_MCU_LP_PARAM_T); + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + // configure CMD_MCU_LP_PARAM_T + prMcuSetOscCmd = (P_CMD_MCU_LP_PARAM_T)(prWifiCmd->aucBuffer); + prMcuSetOscCmd->u2OscStableTime = u2OscStableTime; + + status = wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return status; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update network address in firmware domain +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_FAILURE The request could not be processed +* WLAN_STATUS_PENDING The request has been queued for later processing +* WLAN_STATUS_SUCCESS The request has been processed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanUpdateNetworkAddress ( + IN P_ADAPTER_T prAdapter + ) +{ + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + PARAM_MAC_ADDRESS rMacAddr; + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BASIC_CONFIG prCmdBasicConfig; + UINT_32 u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if(kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE + || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + // eFUSE has a valid address, don't do anything + if(prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, ("Using embedded MAC address")); +#endif + return WLAN_STATUS_SUCCESS; + } + else { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, ("Using dynamically generated MAC address")); +#endif + // dynamic generate + u4SysTime = (UINT_32) kalGetTimeTick(); + + rMacAddr[0] = 0x00; + rMacAddr[1] = 0x08; + rMacAddr[2] = 0x22; + + kalMemCopy(&rMacAddr[3], &u4SysTime, 3); + } + } + else { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, ("Using host-supplied MAC address")); +#endif + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_BUILD_CONNECTION cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + // configure CMD_BASIC_CONFIG + prCmdBasicConfig = (P_CMD_BASIC_CONFIG)(prWifiCmd->aucBuffer); + kalMemCopy(&(prCmdBasicConfig->rMyMacAddr), &rMacAddr, PARAM_MAC_ADDR_LEN); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if(prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(2); + + if(prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(1); + + if(prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(0); + + if(prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(2); + + if(prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(1); + + if(prAdapter->u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(0); +#endif + + if(wlanSendCommand(prAdapter, prCmdInfo) == WLAN_STATUS_RESOURCES) { + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryAddress; + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + return WLAN_STATUS_PENDING; + } + else { + nicCmdEventQueryAddress(prAdapter, prCmdInfo, (PUINT_8)prCmdBasicConfig); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return WLAN_STATUS_SUCCESS; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the device is in RF test mode +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanQueryTestMode( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return prAdapter->fgTestMode; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to identify 802.1x and Bluetooth-over-Wi-Fi +* security frames, and queued into command queue for strict ordering +* due to 802.1x frames before add-key OIDs are not to be encrypted +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prPacket Pointer of native packet +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanProcessSecurityFrame( + IN P_ADAPTER_T prAdapter, + IN P_NATIVE_PACKET prPacket + ) +{ + UINT_8 ucPriorityParam; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen; + ULONG u4SysTime; + UINT_8 ucNetworkType; + P_CMD_INFO_T prCmdInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + + if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, + &fgIsPAL, + &ucNetworkType) == TRUE) { + if(fgIs1x == FALSE) { + return FALSE; + } + else { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + DBGLOG(RSN, INFO, ("T1X len=%d\n", u4PacketLen)); + + if (prCmdInfo) { + P_STA_RECORD_T prStaRec; + // fill arrival time + u4SysTime = (OS_SYSTIME)kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (UINT_16)u4PacketLen; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = prPacket; +#if 0 + prCmdInfo->ucStaRecIndex = qmGetStaRecIdx(prAdapter, + aucEthDestAddr, + (ENUM_NETWORK_TYPE_INDEX_T)ucNetworkType); +#endif + prStaRec = cnmGetStaRecByAddress(prAdapter, + (ENUM_NETWORK_TYPE_INDEX_T)ucNetworkType, + aucEthDestAddr); + if(prStaRec) { + prCmdInfo->ucStaRecIndex = prStaRec->ucIndex; + } + else { + prCmdInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + } + + prCmdInfo->eNetworkType = (ENUM_NETWORK_TYPE_INDEX_T)ucNetworkType; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + return TRUE; + } + else { + ASSERT(0); + return FALSE; + } + } + } + else { + return FALSE; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has been sent to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* @param pucEventBuf meaningless, only for API compatibility +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSecurityFrameTxDone( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + if (prCmdInfo->eNetworkType == NETWORK_TYPE_AIS_INDEX && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); + if (prSta) { + kalMsleep(10); + secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); + } + } + + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, + WLAN_STATUS_SUCCESS); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has failed sending to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSecurityFrameTxTimeout( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, + WLAN_STATUS_FAILURE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called before AIS is starting a new scan +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanClearScanningResult( + IN P_ADAPTER_T prAdapter + ) +{ + BOOLEAN fgKeepCurrOne = FALSE; + UINT_32 i; + + ASSERT(prAdapter); + + // clear scanning result + if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + if(EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + fgKeepCurrOne = TRUE; + + if(i != 0) { + // copy structure + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[0]), + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + } + + if(prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + if(prAdapter->rWlanInfo.apucScanResultIEs[i] != &(prAdapter->rWlanInfo.aucScanIEBuf[0])) { + // move IEs to head + kalMemCopy(prAdapter->rWlanInfo.aucScanIEBuf, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + + // modify IE pointer + prAdapter->rWlanInfo.apucScanResultIEs[0] = &(prAdapter->rWlanInfo.aucScanIEBuf[0]); + } + else { + prAdapter->rWlanInfo.apucScanResultIEs[0] = NULL; + } + + break; + } + } + } + + if(fgKeepCurrOne == TRUE) { + prAdapter->rWlanInfo.u4ScanResultNum = 1; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = + ALIGN_4(prAdapter->rWlanInfo.arScanResult[0].u4IELength); + } + else { + prAdapter->rWlanInfo.u4ScanResultNum = 0; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = 0; + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when AIS received a beacon timeout event +* +* @param prAdapter Pointer of Adapter Data Structure +* @param arBSSID MAC address of the specified BSS +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanClearBssInScanningResult( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 arBSSID + ) +{ + UINT_32 i, j, u4IELength = 0, u4IEMoveLength; + PUINT_8 pucIEPtr; + + ASSERT(prAdapter); + + // clear scanning result + i = 0; + while(1) { + if(i >= prAdapter->rWlanInfo.u4ScanResultNum) { + break; + } + + if(EQUAL_MAC_ADDR(arBSSID, prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + // backup current IE length + u4IELength = ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4IELength); + pucIEPtr = prAdapter->rWlanInfo.apucScanResultIEs[i]; + + // removed from middle + for(j = i + 1 ; j < prAdapter->rWlanInfo.u4ScanResultNum ; j++) { + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[j-1]), + &(prAdapter->rWlanInfo.arScanResult[j]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + prAdapter->rWlanInfo.apucScanResultIEs[j-1] = + prAdapter->rWlanInfo.apucScanResultIEs[j]; + } + + prAdapter->rWlanInfo.u4ScanResultNum--; + + // remove IE buffer if needed := move rest of IE buffer + if(u4IELength > 0) { + u4IEMoveLength = prAdapter->rWlanInfo.u4ScanIEBufferUsage - + (((UINT_32)pucIEPtr) + u4IELength - ((UINT_32)(&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, + (PUINT_8)(((UINT_32)pucIEPtr) + u4IELength), + u4IEMoveLength); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; + + // correction of pointers to IE buffer + for(j = 0 ; j < prAdapter->rWlanInfo.u4ScanResultNum ; j++) { + if(prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { + prAdapter->rWlanInfo.apucScanResultIEs[j] = + (PUINT_8)((UINT_32)(prAdapter->rWlanInfo.apucScanResultIEs[j]) - u4IELength); + } + } + } + } + + i++; + } + + return; +} + + +#if CFG_TEST_WIFI_DIRECT_GO +VOID +wlanEnableP2pFunction ( + IN P_ADAPTER_T prAdapter + ) +{ +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; + + prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(FALSE); + return; + } + + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prMsgFuncSwitch->fgIsFuncOn = TRUE; + + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + return; +} + +VOID +wlanEnableATGO ( + IN P_ADAPTER_T prAdapter + ) +{ + + P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)NULL; + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + if (!prMsgConnReq) { + ASSERT(FALSE); + return; + } + + prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + /*=====Param Modified for test=====*/ + COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); + prMsgConnReq->fgIsTobeGO = TRUE; + prMsgConnReq->fgIsPersistentGroup = FALSE; + + /*=====Param Modified for test=====*/ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgConnReq, + MSG_SEND_METHOD_BUF); + + return; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve permanent address from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryPermanentAddress( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryPermanentAddress"); + + // 1. Allocate CMD Info Packet and its Buffer + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_BUILD_CONNECTION cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if(nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + return WLAN_STATUS_FAILURE; + } + + // header checking .. + prHifRxHdr = (P_HIF_RX_HEADER_T)aucBuffer; + if(prHifRxHdr->u2PacketType != HIF_RX_PKT_TYPE_EVENT) { + return WLAN_STATUS_FAILURE; + } + + prEvent = (P_WIFI_EVENT_T)aucBuffer; + if(prEvent->ucEID != EVENT_ID_BASIC_CONFIG) { + return WLAN_STATUS_FAILURE; + } + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG)(prEvent->aucBuffer); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, &(prEventBasicConfig->rMyMacAddr)); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, &(prEventBasicConfig->rMyMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryNicCapability( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_NIC_CAPABILITY prEventNicCapability; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryNicCapability"); + + // 1. Allocate CMD Info Packet and its Buffer + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_BUILD_CONNECTION cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if(nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + return WLAN_STATUS_FAILURE; + } + + // header checking .. + prHifRxHdr = (P_HIF_RX_HEADER_T)aucBuffer; + if(prHifRxHdr->u2PacketType != HIF_RX_PKT_TYPE_EVENT) { + return WLAN_STATUS_FAILURE; + } + + prEvent = (P_WIFI_EVENT_T)aucBuffer; + if(prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { + return WLAN_STATUS_FAILURE; + } + + prEventNicCapability = (P_EVENT_NIC_CAPABILITY)(prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; + prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; + prAdapter->fgIsHw5GBandDisabled = (BOOLEAN)prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = (BOOLEAN)prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEfuseValid = (BOOLEAN)prEventNicCapability->ucEfuseValid; + prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN)prEventNicCapability->ucMacAddrValid; + + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, INFO, (" RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail ,prEventNicCapability->ucBbCalFail )); +#endif + return WLAN_STATUS_SUCCESS; +} + +#ifdef MT6628 +static INT_32 wlanChangeCodeWord(INT_32 au4Input){ + + UINT_16 i; +#if TXPWR_USE_PDSLOPE + CODE_MAPPING_T arCodeTable[] = { + {0X100, -40}, + {0X104, -35}, + {0X128, -30}, + {0X14C, -25}, + {0X170, -20}, + {0X194, -15}, + {0X1B8, -10}, + {0X1DC, - 5}, + {0 , 0}, + {0X24 , 5}, + {0X48 , 10}, + {0X6C , 15}, + {0X90 , 20}, + {0XB4 , 25}, + {0XD8 , 30}, + {0XFC , 35}, + {0XFF , 40}, + + }; +#else + CODE_MAPPING_T arCodeTable[] = { + {0X100, 0x80}, + {0X104, 0x80}, + {0X128, 0x80}, + {0X14C, 0x80}, + {0X170, 0x80}, + {0X194, 0x94}, + {0X1B8, 0XB8}, + {0X1DC, 0xDC}, + {0 , 0}, + {0X24 , 0x24}, + {0X48 , 0x48}, + {0X6C , 0x6c}, + {0X90 , 0x7F}, + {0XB4 , 0x7F}, + {0XD8 , 0x7F}, + {0XFC , 0x7F}, + {0XFF , 0x7F}, + + }; +#endif + + for (i = 0; i < sizeof(arCodeTable) / sizeof(CODE_MAPPING_T); i++) { + + if (arCodeTable[i].u4RegisterValue == au4Input){ + return arCodeTable[i] .u4TxpowerOffset; + } + } + + + return 0; +} +#endif +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryPdMcr( + IN P_ADAPTER_T prAdapter, + P_PARAM_MCR_RW_STRUC_T prMcrRdInfo + ) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_CMD_ACCESS_REG prCmdMcrQuery; + ASSERT(prAdapter); + + + // 1. Allocate CMD Info Packet and its Buffer + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_BUILD_CONNECTION cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_ACCESS_REG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, sizeof(CMD_ACCESS_REG)); + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if(nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + return WLAN_STATUS_FAILURE; + } + + // header checking .. + prHifRxHdr = (P_HIF_RX_HEADER_T)aucBuffer; + if(prHifRxHdr->u2PacketType != HIF_RX_PKT_TYPE_EVENT) { + return WLAN_STATUS_FAILURE; + } + + + prEvent = (P_WIFI_EVENT_T)aucBuffer; + + if(prEvent->ucEID != EVENT_ID_ACCESS_REG) { + return WLAN_STATUS_FAILURE; + } + + prCmdMcrQuery = (P_CMD_ACCESS_REG)(prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +static INT_32 wlanIntRound(INT_32 au4Input) +{ + + + if (au4Input >= 0){ + if((au4Input%10) == 5){ + au4Input = au4Input + 5; + return au4Input; + } + } + + if (au4Input < 0){ + if((au4Input%10) == -5){ + au4Input = au4Input - 5; + return au4Input; + } + } + + return au4Input; +} + +static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter,INT_32 au4Input){ + + PARAM_MCR_RW_STRUC_T rMcrRdInfo; + INT_32 au4PdSlope,au4TxPwrOffset,au4TxPwrOffset_Round; + INT_8 auTxPwrOffset_Round; + + rMcrRdInfo.u4McrOffset = 0x60205c68; + rMcrRdInfo.u4McrData = 0; + au4TxPwrOffset = au4Input; + wlanQueryPdMcr(prAdapter,&rMcrRdInfo); + + au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0,6); + au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset*au4PdSlope))/10; + + au4TxPwrOffset_Round = -au4TxPwrOffset_Round; + + if(au4TxPwrOffset_Round < -128) { + au4TxPwrOffset_Round = 128; + } + else if (au4TxPwrOffset_Round < 0){ + au4TxPwrOffset_Round += 256; + } + else if (au4TxPwrOffset_Round > 127){ + au4TxPwrOffset_Round = 127; + } + + auTxPwrOffset_Round = (UINT8) au4TxPwrOffset_Round ; + + return au4TxPwrOffset_Round; +} + +#endif + +#ifdef MT6628 +static VOID wlanChangeNvram6620to6628(PUINT_8 pucEFUSE){ + + + #define EFUSE_CH_OFFSET1_L_MASK_6620 BITS(0,8) + #define EFUSE_CH_OFFSET1_L_SHIFT_6620 0 + #define EFUSE_CH_OFFSET1_M_MASK_6620 BITS(9,17) + #define EFUSE_CH_OFFSET1_M_SHIFT_6620 9 + #define EFUSE_CH_OFFSET1_H_MASK_6620 BITS(18,26) + #define EFUSE_CH_OFFSET1_H_SHIFT_6620 18 + #define EFUSE_CH_OFFSET1_VLD_MASK_6620 BIT(27) + #define EFUSE_CH_OFFSET1_VLD_SHIFT_6620 27 + + #define EFUSE_CH_OFFSET1_L_MASK_5931 BITS(0,7) + #define EFUSE_CH_OFFSET1_L_SHIFT_5931 0 + #define EFUSE_CH_OFFSET1_M_MASK_5931 BITS(8,15) + #define EFUSE_CH_OFFSET1_M_SHIFT_5931 8 + #define EFUSE_CH_OFFSET1_H_MASK_5931 BITS(16,23) + #define EFUSE_CH_OFFSET1_H_SHIFT_5931 16 + #define EFUSE_CH_OFFSET1_VLD_MASK_5931 BIT(24) + #define EFUSE_CH_OFFSET1_VLD_SHIFT_5931 24 + #define EFUSE_ALL_CH_OFFSET1_MASK_5931 BITS(25,27) + #define EFUSE_ALL_CH_OFFSET1_SHIFT_5931 25 + + + + + INT_32 au4ChOffset; + INT_16 au2ChOffsetL,au2ChOffsetM,au2ChOffsetH; + + + au4ChOffset = *(UINT_32*)(pucEFUSE + 72); + + if((au4ChOffset & EFUSE_CH_OFFSET1_VLD_MASK_6620) && ((*(UINT_32*)(pucEFUSE + 28)) == 0)) { + + + au2ChOffsetL = ((au4ChOffset & EFUSE_CH_OFFSET1_L_MASK_6620) >> + EFUSE_CH_OFFSET1_L_SHIFT_6620); + + au2ChOffsetM = ((au4ChOffset & EFUSE_CH_OFFSET1_M_MASK_6620) >> + EFUSE_CH_OFFSET1_M_SHIFT_6620); + + au2ChOffsetH = ((au4ChOffset & EFUSE_CH_OFFSET1_H_MASK_6620) >> + EFUSE_CH_OFFSET1_H_SHIFT_6620); + + au2ChOffsetL = wlanChangeCodeWord(au2ChOffsetL); + au2ChOffsetM = wlanChangeCodeWord(au2ChOffsetM); + au2ChOffsetH = wlanChangeCodeWord(au2ChOffsetH); + + au4ChOffset = 0; + au4ChOffset |= *(UINT_32*)(pucEFUSE + 72) + >> (EFUSE_CH_OFFSET1_VLD_SHIFT_6620 - EFUSE_CH_OFFSET1_VLD_SHIFT_5931 )& EFUSE_CH_OFFSET1_VLD_MASK_5931 ; + + + + au4ChOffset |= ((((UINT_32)au2ChOffsetL) << EFUSE_CH_OFFSET1_L_SHIFT_5931) & EFUSE_CH_OFFSET1_L_MASK_5931); + au4ChOffset |= ((((UINT_32)au2ChOffsetM) << EFUSE_CH_OFFSET1_M_SHIFT_5931) & EFUSE_CH_OFFSET1_M_MASK_5931); + au4ChOffset |= ((((UINT_32)au2ChOffsetH) << EFUSE_CH_OFFSET1_H_SHIFT_5931) & EFUSE_CH_OFFSET1_H_MASK_5931); + + *((INT_32 *)((pucEFUSE + 28))) = au4ChOffset ; + + + + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to load manufacture data from NVRAM +* if available and valid +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prRegInfo Pointer of REG_INFO_T +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanLoadManufactureData ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + CMD_RDD_CH_T rRddParam; +#endif + + ASSERT(prAdapter); + + /* 1. Version Check */ + kalGetConfigurationVersion(prAdapter->prGlueInfo, + &(prAdapter->rVerInfo.u2Part1CfgOwnVersion), + &(prAdapter->rVerInfo.u2Part1CfgPeerVersion), + &(prAdapter->rVerInfo.u2Part2CfgOwnVersion), + &(prAdapter->rVerInfo.u2Part2CfgPeerVersion)); + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + if(CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION) { + return WLAN_STATUS_FAILURE; + } +#endif + + // MT6620 E1/E2 would be ignored directly + if(prAdapter->rVerInfo.u2Part1CfgOwnVersion == 0x0001) { + prRegInfo->ucTxPwrValid = 1; + } + else { + /* 2. Load TX power gain parameters if valid */ + if(prRegInfo->ucTxPwrValid != 0) { + // send to F/W + nicUpdateTxPower(prAdapter, (P_CMD_TX_PWR_T)(&(prRegInfo->rTxPwr))); + } + } + + /* 3. Check if needs to support 5GHz */ + if(prRegInfo->ucEnable5GBand) { + // check if it is disabled by hardware + if(prAdapter->fgIsHw5GBandDisabled + || prRegInfo->ucSupport5GBand == 0) { + prAdapter->fgEnable5GBand = FALSE; + } + else { + prAdapter->fgEnable5GBand = TRUE; + } + } + else { + prAdapter->fgEnable5GBand = FALSE; + } + + /* 4. Send EFUSE data */ +#if defined(MT6628) + wlanChangeNvram6620to6628(prRegInfo->aucEFUSE); +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_PHY_PARAM_T), + (PUINT_8)(prRegInfo->aucEFUSE), + NULL, + 0); + +#if CFG_SUPPORT_RDD_TEST_MODE + rRddParam.ucRddTestMode = (UINT_8) prRegInfo->u4RddTestMode; + rRddParam.ucRddShutCh = (UINT_8) prRegInfo->u4RddShutFreq; + rRddParam.ucRddStartCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStartFreq); + rRddParam.ucRddStopCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStopFreq); + rRddParam.ucRddDfs = (UINT_8) prRegInfo->u4RddDfs; + prAdapter->ucRddStatus = 0; + nicUpdateRddTestMode(prAdapter, (P_CMD_RDD_CH_T)(&rRddParam)); +#endif + + /* 5. Get 16-bits Country Code and Bandwidth */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) prRegInfo->au2CountryCode[0]) << 8) | + (((UINT_16) prRegInfo->au2CountryCode[1]) & BITS(0,7)); + +#if 0 /* Bandwidth control will be controlled by GUI. 20110930 + * So ignore the setting from registry/NVRAM + */ + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = + prRegInfo->uc2G4BwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = + prRegInfo->uc5GBwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; +#endif + + /* 6. Set domain and channel information to chip */ + rlmDomainSendCmd(prAdapter, FALSE); + + /* 7. set band edge tx power if available */ + if(prRegInfo->fg2G4BandEdgePwrUsed) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK + = prRegInfo->cBandEdgeMaxPwrCCK; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 + = prRegInfo->cBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 + = prRegInfo->cBandEdgeMaxPwrOFDM40; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_EDGE_TXPWR_LIMIT_T), + (PUINT_8)&rCmdEdgeTxPwrLimit, + NULL, + 0); + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check +* Media Stream Mode is set to non-default value or not, +* and clear to default value if above criteria is met +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return TRUE +* The media stream mode was non-default value and has been reset +* FALSE +* The media stream mode is default value +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanResetMediaStreamMode( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + if(prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode != 0) { + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + + return TRUE; + } + else { + return FALSE; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending timer has expired +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanTimerTimeoutCheck( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + cnmTimerDoTimeOutCheck(prAdapter); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending mailbox message +* to be handled +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanProcessMboxMessage( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i; + + ASSERT(prAdapter); + + for(i = 0 ; i < MBOX_ID_TOTAL_NUM ; i++) { + mboxRcvAllMsg(prAdapter , (ENUM_MBOX_ID_T)i); + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to enqueue a single TX packet into CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* prNativePacket Pointer of Native Packet +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_RESOURCES +* WLAN_STATUS_INVALID_PACKET +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanEnqueueTxPacket ( + IN P_ADAPTER_T prAdapter, + IN P_NATIVE_PACKET prNativePacket + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if(prMsduInfo == NULL) { + return WLAN_STATUS_RESOURCES; + } + else { + prMsduInfo->eSrc = TX_PACKET_OS; + + if(nicTxFillMsduInfo(prAdapter, + prMsduInfo, + prNativePacket) == FALSE) { // packet is not extractable + kalSendComplete(prAdapter->prGlueInfo, + prNativePacket, + WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + } + else { + // enqueue to QM + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to flush pending TX packets in CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanFlushTxPendingPackets( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return nicTxFlush(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function sends pending MSDU_INFO_T to MT6620 +* +* @param prAdapter Pointer to the Adapter structure. +* @param pfgHwAccess Pointer for tracking LP-OWN status +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanTxPendingPackets ( + IN P_ADAPTER_T prAdapter, + IN OUT PBOOLEAN pfgHwAccess + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(pfgHwAccess); + + // <1> dequeue packet by txDequeuTxPackets() + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPackets(prAdapter, &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if(prMsduInfo != NULL) { + if(kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + /* <2> Acquire LP-OWN if necessary */ + if(*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == TRUE) { + nicDisableClockGating(prAdapter); + } +#endif + // <3> send packets + nicTxMsduInfoList(prAdapter, prMsduInfo); + + // <4> update TC by txAdjustTcQuotas() + nicTxAdjustTcq(prAdapter); + } + else { + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + } + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == FALSE) { + nicEnableClockGating(prAdapter); + } +#endif + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to acquire power control from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAcquirePowerControl( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if(prAdapter->fgWiFiInSleepyState == TRUE) { + prAdapter->fgWiFiInSleepyState = FALSE; + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to release power control to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanReleasePowerControl( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to report currently pending TX frames count +* (command packets are not included) +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return number of pending TX frames +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +wlanGetTxPendingFrameCount ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + UINT_32 u4Num; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + (UINT_32)(prTxCtrl->i4PendingFwdFrameCount); + + return u4Num; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to report current ACPI state +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +*/ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T +wlanGetAcpiState ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return prAdapter->rAcpiState; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to update current ACPI state only +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ePowerState ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetAcpiState ( + IN P_ADAPTER_T prAdapter, + IN ENUM_ACPI_STATE_T ePowerState + ) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query ECO version from HIFSYS CR +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +wlanGetEcoVersion( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + if(nicVerifyChipID(prAdapter) == TRUE) { + return (prAdapter->ucRevID + 1); + } + else { + return 0; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to setting the default Tx Power configuration +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanDefTxPowerCfg ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 i; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_SET_TXPWR_CTRL_T prTxpwr; + + ASSERT(prGlueInfo); + + prTxpwr = &prGlueInfo->rTxPwr; + + prTxpwr->c2GLegacyStaPwrOffset = 0; + prTxpwr->c2GHotspotPwrOffset = 0; + prTxpwr->c2GP2pPwrOffset = 0; + prTxpwr->c2GBowPwrOffset = 0; + prTxpwr->c5GLegacyStaPwrOffset = 0; + prTxpwr->c5GHotspotPwrOffset = 0; + prTxpwr->c5GP2pPwrOffset = 0; + prTxpwr->c5GBowPwrOffset = 0; + prTxpwr->ucConcurrencePolicy = 0; + for (i=0; i<3;i++) + prTxpwr->acReserved1[i] = 0; + + for (i=0; i<14;i++) + prTxpwr->acTxPwrLimit2G[i] = 63; + + for (i=0; i<4;i++) + prTxpwr->acTxPwrLimit5G[i] = 63; + + for (i=0; i<2;i++) + prTxpwr->acReserved2[i] = 0; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* set preferred band configuration corresponding to network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eBand Given band +* @param eNetTypeIndex Given Network Type +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[eNetTypeIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if(eBand == BAND_2G4) { + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, eNetTypeIndex); + } + else if(eBand == BAND_5G) { + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, eNetTypeIndex); + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get channel information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +wlanGetChannelNumberByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + return prBssInfo->ucPrimaryChannel; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get BSS descriptor information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return pointer to BSS_DESC_T +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +wlanGetTargetBssDescByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + switch(eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + return prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + case NETWORK_TYPE_P2P_INDEX: + return NULL; + + case NETWORK_TYPE_BOW_INDEX: + return prAdapter->rWifiVar.rBowFsmInfo.prTargetBssDesc; + + default: + return NULL; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* check unconfigured system properties and generate related message on +* scan list to notify users +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanCheckSystemConfiguration ( + IN P_ADAPTER_T prAdapter + ) +{ +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + BOOLEAN fgIsConfExist = TRUE; + BOOLEAN fgGenErrMsg = FALSE; + P_REG_INFO_T prRegInfo = NULL; + P_WLAN_BEACON_FRAME_T prBeacon = NULL; + P_IE_SSID_T prSsid = NULL; + UINT_32 u4ErrCode = 0; + UINT_8 aucErrMsg[32]; + PARAM_SSID_T rSsid; + PARAM_802_11_CONFIG_T rConfiguration; + PARAM_RATES_EX rSupportedRates; +#endif + + DEBUGFUNC("wlanCheckSystemConfiguration"); + + ASSERT(prAdapter); + +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) + if(kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { + fgIsConfExist = FALSE; + fgGenErrMsg = TRUE; + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + prRegInfo = kalGetConfiguration(prAdapter->prGlueInfo); + + if(fgIsConfExist == TRUE && + (CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION + || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) + || prRegInfo->ucTxPwrValid == 0)) { + fgGenErrMsg = TRUE; + } +#endif + + if(fgGenErrMsg == TRUE) { + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + + // initialization + kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + + // prBeacon initialization + prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; + COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); + COPY_MAC_ADDR(prBeacon->aucSrcAddr, aucZeroMacAddr); + COPY_MAC_ADDR(prBeacon->aucBSSID, aucZeroMacAddr); + prBeacon->u2BeaconInterval = 100; + prBeacon->u2CapInfo = CAP_INFO_ESS; + + // prSSID initialization + prSsid = (P_IE_SSID_T)(&prBeacon->aucInfoElem[0]); + prSsid->ucId = ELEM_ID_SSID; + + // rConfiguration initialization + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = 100; + rConfiguration.u4ATIMWindow = 1; + rConfiguration.u4DSConfig = 2412; + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + // rSupportedRates initialization + kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); + } + +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) + #define NVRAM_ERR_MSG "NVRAM WARNING: Err = 0x01" + if(kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { + COPY_SSID(prSsid->aucSSID, + prSsid->ucLength, + NVRAM_ERR_MSG, + strlen(NVRAM_ERR_MSG)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8)prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength, + 1, + 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8)((UINT_32)(prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + #define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" + if(fgIsConfExist == TRUE) { + if((CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION)) { + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + } + + + if(prRegInfo->ucTxPwrValid == 0) { + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + } + + if(prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) { + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + } + + if(u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, + prSsid->ucLength, + aucErrMsg, + strlen(aucErrMsg)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8)prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength, + 1, + 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8)((UINT_32)(prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if(fgGenErrMsg == TRUE) { + cnmMemFree(prAdapter, prBeacon); + } + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c new file mode 100755 index 000000000000..25a13a7ddc23 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c @@ -0,0 +1,10787 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_oid.c#5 $ +*/ + +/*! \file wlanoid.c + \brief This file contains the WLAN OID processing routines of Windows driver for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_oid.c $ +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * using the wlanSendSetQueryCmd to set the tx power control cmd. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * change the set tx power cmd name. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 12 20 2011 cp.wu + * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information + * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO + * to expose version information + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 21 2011 cp.wu + * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing + * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer + * add more checking for such cases + * + * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. + * add some tweaking to protect such cases because that net device has become invalid. + * + * 11 15 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 11 09 2011 george.huang + * [WCXRP00000871] [MT6620 Wi-Fi][FW] Include additional wakeup condition, which is by consequent DTIM unicast indication + * add XLOG for Set PS mode entry + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 11 02 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add RDD certification features. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 15 2011 tsaiyuan.hsu + * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA + * correct fifo full control from query to set operation for CTIA. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 17 2011 tsaiyuan.hsu + * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA + * add system config for CTIA. + * + * 08 15 2011 george.huang + * [MT6620 Wi-Fi][FW] handle TSF drift for connection detection + * . + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 05 02 2011 eddie.chen + * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control + * Fix compile warning. + * + * 04 29 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * . + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * add more debug message + * + * 04 26 2011 eddie.chen + * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control + * Add rx path profiling. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 31 2011 puff.wen + * NULL + * . + * + * 03 29 2011 puff.wen + * NULL + * Add chennel switch for stress test + * + * 03 29 2011 cp.wu + * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning + * surpress klock warning with code path rewritten + * + * 03 24 2011 wh.su + * [WCXRP00000595] [MT6620 Wi-Fi][Driver] at CTIA indicate disconnect to make the ps profile can apply + * use disconnect event instead of ais abort for CTIA testing. + * + * 03 23 2011 george.huang + * [WCXRP00000586] [MT6620 Wi-Fi][FW] Modify for blocking absence request right after connected + * revise for CTIA power mode setting + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 17 2011 yarco.yang + * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage + * . + * + * 03 15 2011 george.huang + * [WCXRP00000557] [MT6620 Wi-Fi] Support current consumption test mode commands + * Support current consumption measurement mode command + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 04 2011 cp.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * surpress compile warning occured when compiled by GNU compiler collection. + * + * 03 03 2011 wh.su + * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue + * fixed the enter ctia test mode issue. + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Update sigma CAPI for U-APSD setting + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 01 27 2011 george.huang + * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting + * Support CTIA power mode setting. + * + * 01 26 2011 wh.su + * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux + * adding the SW cmd ioctl support, use set/get structure ioctl. + * + * 01 25 2011 cp.wu + * [WCXRP00000394] [MT6620 Wi-Fi][Driver] Count space needed for generating error message in scanning list into buffer size checking + * when doing size prechecking, check illegal MAC address as well + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cp.wu + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * check if allow to switch to IBSS mode via concurrent module before setting to IBSS mode + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 01 04 2011 cp.wu + * [WCXRP00000342] [MT6620 Wi-Fi][Driver] show error code in scanning list when MAC address is not correctly configured in NVRAM + * show error code 0x10 when MAC address in NVRAM is not configured correctly. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 28 2010 george.huang + * [WCXRP00000232] [MT5931 Wi-Fi][FW] Modifications for updated HW power on sequence and related design + * support WMM-PS U-APSD AC assignment. + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 16 2010 cp.wu + * [WCXRP00000268] [MT6620 Wi-Fi][Driver] correction for WHQL failed items + * correction for OID_802_11_NETWORK_TYPES_SUPPORTED handlers + * + * 12 13 2010 cp.wu + * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork + * suppress warning reported by Klockwork. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 30 2010 cp.wu + * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 + * . + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not availble then warning message is shown + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 21 2010 wh.su + * [WCXRP00000192] [MT6620 Wi-Fi][Driver] Fixed fail trying to build connection with Security AP while enable WAPI message check + * Not set the wapi mode while the wapi assoc info set non-wapi ie. + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 22 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * dos2unix conversion. + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 06 2010 yuche.tsai + * NULL + * Update SLT 5G Test Channel Set. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 06 2010 yuche.tsai + * NULL + * Update For SLT 5G Test Channel Selection Rule. + * + * 10 05 2010 cp.wu + * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form + * Query buffer size needs to be enlarged due to result is filled in 4-bytes alignment boundary + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 10 04 2010 cp.wu + * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form + * Extend result length to multiples of 4-bytes + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Update SLT due to API change of SCAN module. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 yuche.tsai + * NULL + * Refine SLT IO control handler. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 chinglan.wang + * NULL + * Modify the rescan condition. + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 27 2010 chinglan.wang + * NULL + * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 16 2010 george.huang + * NULL + * . + * + * 08 16 2010 george.huang + * NULL + * upate params defined in CMD_SET_NETWORK_ADDRESS_LIST + * + * 08 04 2010 cp.wu + * NULL + * fix for check build WHQL testing: + * 1) do not assert query buffer if indicated buffer length is zero + * 2) sdio.c has bugs which cause freeing same pointer twice + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 04 2010 cp.wu + * NULL + * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. + * + * 08 04 2010 cp.wu + * NULL + * bypass u4FuncData for RF-Test query request as well. + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 26 2010 cp.wu + * + * re-commit code logic being overwriten. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 20 2010 cp.wu + * + * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one + * 2) refine disconnection behaviour when issued during BG-SCAN process + * + * 07 19 2010 wh.su + * + * modify the auth and encry status variable. + * + * 07 16 2010 cp.wu + * + * remove work-around in case SCN is not available. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. + * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add SCN compilation option. + * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement SCAN-REQUEST oid as mailbox message dispatching. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * adding the compiling flag for oid pmkid. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * simplify cmd packet sending for RF test and MCR access OIDs + * + * 05 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable radio even when STA is not associated. + * + * 05 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct 2 OID behaviour to meet WHQL requirement. + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power managment macro + * + * 05 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct BSSID_LIST oid when radio if turned off. + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll + * 2) correct address list parsing + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable wlanoidSetNetworkAddress() temporally. + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * some OIDs should be DRIVER_CORE instead of GLUE_EXTENSION + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. + * 2) finish statistics OIDs + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct wlanoidSet802dot11PowerSaveProfile implementation. + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) enable CMD/EVENT ver 0.9 definition. + * 2) abandon use of ENUM_MEDIA_STATE + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add dissassocation support for wpa supplicant + * + * 05 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct return value. + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * for disassociation, still use parameter with current setting. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * for disassociation, generate a WZC-compatible invalid SSID. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * associate to illegal SSID when handling OID_802_11_DISASSOCIATE + * + * 04 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * reserve field of privacy filter and RTS threshold setting. + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 04 22 2010 cp.wu + * [WPD00003830]add OID_802_11_PRIVACY_FILTER support + * enable RX filter OID + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add ioctl of power management + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * 2) command sequence number is now increased atomically + * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_CONFIGURATION query for infrastructure mode. + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) remove unused spin lock declaration + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * are done in adapter layer. + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)improve none-glue code portability + * (2) disable set Multicast address during atomic context + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve glue code portability + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * the frequency is used for adhoc connection only + * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * + * + * 03 22 2010 cp.wu + * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list + * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result + * + * 03 19 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * adding the check for pass WHQL test item. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * +* 03 16 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * fixed some whql pre-test fail case. + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. + * + * 02 24 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Don't needed to check the auth mode, WHQL testing not specific at auth wpa2. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not check SSID validity anymore. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * 2. follow MSDN defined behavior when associates to another AP + * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move ucCmdSeqNum as instance variable + * + * 02 04 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when OID_CUSTOM_OID_INTERFACE_VERSION is queried, do modify connection states + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * 2. block TX/ordinary OID when RF test mode is engaged + * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * 4. correct some HAL implementation + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * OID_802_11_RSSI, + * OID_802_11_RSSI_TRIGGER, + * OID_802_11_STATISTICS, + * OID_802_11_DISASSOCIATE, + * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not fill ucJoinOnly currently + * + * 01 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable to connect to ad-hoc network + * + * 01 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * .implement Set/Query BeaconInterval/AtimWindow + * + * 01 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * .Set/Get AT Info is not blocked even when driver is not in fg test mode + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * and result is retrieved by get ATInfo instead + * 2) add 4 counter for recording aggregation statistics + * + * 12 28 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate redundant variables for connection_state +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-16 22:13:36 GMT mtk02752 +** change hard-coded MAC address to match with FW (temporally) +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-10 16:49:50 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-08 17:38:49 GMT mtk02752 +** + add OID for RF test +** * MCR RD/WR are modified to match with cmd/event definition +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-12-08 11:32:20 GMT mtk02752 +** add skeleton for RF test implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-12-03 16:43:24 GMT mtk01461 +** Modify query SCAN list oid by adding prEventScanResult +** +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-03 16:39:27 GMT mtk01461 +** Sync CMD data structure in set ssid oid +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-03 16:28:22 GMT mtk01461 +** Add invalid check of set SSID oid and fix query scan list oid +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-30 17:33:08 GMT mtk02752 +** implement wlanoidSetInfrastructureMode/wlanoidQueryInfrastructureMode +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-30 10:53:49 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-30 09:22:48 GMT mtk02752 +** correct wifi cmd length mismatch +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-25 21:34:33 GMT mtk02752 +** sync EVENT_SCAN_RESULT_T with firmware +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 21:03:27 GMT mtk02752 +** implement wlanoidQueryBssidList() +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-25 18:17:17 GMT mtk02752 +** refine GL_WLAN_INFO_T for buffering scan result +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-23 20:28:51 GMT mtk02752 +** some OID will be set to WLAN_STATUS_PENDING until it is sent via wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-23 17:56:36 GMT mtk02752 +** implement wlanoidSetBssidListScan(), wlanoidSetBssid() and wlanoidSetSsid() +** +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-13 17:20:53 GMT mtk02752 +** add Set BSSID/SSID path but disabled temporally due to FW is not ready yet +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 12:28:58 GMT mtk02752 +** add wlanoidSetBssidListScan -> cmd_info path +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-09 22:48:07 GMT mtk01084 +** modify test cases entry +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-04 14:10:58 GMT mtk01084 +** add new test interfaces +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-30 18:17:10 GMT mtk01084 +** fix compiler warning +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:46:26 GMT mtk01084 +** add test functions +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:07:56 GMT mtk01084 +** include new file +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:29 GMT mtk01084 +** modify for new HW architecture +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-02 13:48:49 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-09-09 17:26:04 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-21 12:09:50 GMT mtk01461 +** Update for MCR Write OID +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:35:18 GMT mtk01461 +** Update wlanoidQueryMcrRead() for composing CMD_INFO_T +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 18:09:51 GMT mtk01426 +** Remove kalIndicateStatusAndComplete() in wlanoidQueryOidInterfaceVersion() +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-14 15:51:50 GMT mtk01426 +** Add MCR read/write support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:40 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:06:31 GMT mtk01426 +** Init for develop +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "mgmt/rsn.h" + +#include + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ +#if DBG +extern UINT_8 aucDebugModule[DBG_MODULE_NUM]; +extern UINT_32 u4DebugModule; +UINT_32 u4DebugModuleTemp; +#endif /* DBG */ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +extern int sprintf(char * buf, const char * fmt, ...); + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +#if CFG_ENABLE_STATISTICS_BUFFERING +static BOOLEAN +IsBufferedStatisticsUsable( + P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if(prAdapter->fgIsStatValid == TRUE && + (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= CFG_STATISTICS_VALID_CYCLE) + return TRUE; + else + return FALSE; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the supported physical layer network +* type that can be used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + UINT_32 u4NumItem = 0; + ENUM_PARAM_NETWORK_TYPE_T eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + PPARAM_NETWORK_TYPE_LIST prSupported; + + /* The array of all physical layer network subtypes that the driver supports. */ + + DEBUGFUNC("wlanoidQueryNetworkTypesSupported"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + /* Init. */ + for (u4NumItem = 0; u4NumItem < PARAM_NETWORK_TYPE_NUM ; u4NumItem++) { + eSupportedNetworks[u4NumItem] = 0; + } + + u4NumItem = 0; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_DS; + u4NumItem ++; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_OFDM24; + u4NumItem ++; + + *pu4QueryInfoLen = + (UINT_32)OFFSET_OF(PARAM_NETWORK_TYPE_LIST, eNetworkType) + + (u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prSupported = (PPARAM_NETWORK_TYPE_LIST)pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, + eSupportedNetworks, + u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + DBGLOG(REQ, TRACE, ("NDIS supported network type list: %ld\n", + prSupported->NumberOfItems)); + DBGLOG_MEM8(REQ, INFO, prSupported, *pu4QueryInfoLen); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypesSupported */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current physical layer network +* type used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypeInUse ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + // TODO: need to check the OID handler content again!! + + ENUM_PARAM_NETWORK_TYPE_T rCurrentNetworkTypeInUse = PARAM_NETWORK_TYPE_OFDM24; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + rCurrentNetworkTypeInUse = + (ENUM_PARAM_NETWORK_TYPE_T)(prAdapter->rWlanInfo.ucNetworkType); + } + else { + rCurrentNetworkTypeInUse = + (ENUM_PARAM_NETWORK_TYPE_T)(prAdapter->rWlanInfo.ucNetworkTypeInUse); + } + + *(P_ENUM_PARAM_NETWORK_TYPE_T)pvQueryBuffer = rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(REQ, TRACE, ("Network type in use: %d\n", rCurrentNetworkTypeInUse)); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypeInUse */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the physical layer network type used +* by the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS The given network type is supported and accepted. +* \retval WLAN_STATUS_INVALID_DATA The given network type is not in the +* supported list. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkTypeInUse ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + // TODO: need to check the OID handler content again!! + + ENUM_PARAM_NETWORK_TYPE_T eNewNetworkType; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(P_ENUM_PARAM_NETWORK_TYPE_T)pvSetBuffer; + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(REQ, + INFO, + ("New network type: %d mode\n", eNewNetworkType)); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_AUTOMODE; + break; + + case PARAM_NETWORK_TYPE_FH: + DBGLOG(REQ, INFO, ("Not support network type: %d\n", eNewNetworkType)); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + + default: + DBGLOG(REQ, INFO, ("Unknown network type: %d\n", eNewNetworkType)); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + /* Verify if we support the new network type. */ + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("Unknown network type: %d\n", eNewNetworkType)); + } + + return rStatus; +} /* wlanoidSetNetworkTypeInUse */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current BSSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssid ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryBssid"); + + ASSERT(prAdapter); + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + ASSERT(pu4QueryInfoLen); + *pu4QueryInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(u4QueryBufferLen >= MAC_ADDR_LEN); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + kalMemCopy(pvQueryBuffer, prAdapter->rWlanInfo.rCurrBssId.arMacAddress, MAC_ADDR_LEN); + } + else if(prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS) { + PARAM_MAC_ADDRESS aucTemp; /*!< BSSID */ + COPY_MAC_ADDR(aucTemp, prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + aucTemp[0] &= ~BIT(0); + aucTemp[1] |= BIT(1); + COPY_MAC_ADDR(pvQueryBuffer, aucTemp); + } + else { + rStatus = WLAN_STATUS_ADAPTER_NOT_READY; + } + + *pu4QueryInfoLen = MAC_ADDR_LEN; + return rStatus; +} /* wlanoidQueryBssid */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the list of all BSSIDs detected by +* the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssidList ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4BssidListExLen; + P_PARAM_BSSID_LIST_EX_T prList; + P_PARAM_BSSID_EX_T prBssidEx; + PUINT_8 cp; + + DEBUGFUNC("wlanoidQueryBssidList"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + + if(!pvQueryBuffer) { + return WLAN_STATUS_INVALID_DATA; + } + } + + prGlueInfo = prAdapter->prGlueInfo; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in qeury BSSID list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + u4BssidListExLen = 0; + + if(prAdapter->fgIsRadioOff == FALSE) { + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + u4BssidListExLen += ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4Length); + } + } + + if(u4BssidListExLen) { + u4BssidListExLen += 4; // u4NumberOfItems. + } + else { + u4BssidListExLen = sizeof(PARAM_BSSID_LIST_EX_T); + } + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (P_PARAM_BSSID_LIST_EX_T) pvQueryBuffer; + cp = (PUINT_8)&prList->arBssid[0]; + + if(prAdapter->fgIsRadioOff == FALSE && prAdapter->rWlanInfo.u4ScanResultNum > 0) { + // fill up for each entry + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + prBssidEx = (P_PARAM_BSSID_EX_T)cp; + + // copy structure + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /*For WHQL test, Rssi should be in range -10 ~ -200 dBm*/ + if(prBssidEx->rRssi > PARAM_WHQL_RSSI_MAX_DBM) { + prBssidEx->rRssi = PARAM_WHQL_RSSI_MAX_DBM; + } + + if(prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + // copy IEs + kalMemCopy(prBssidEx->aucIEs, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + + // 4-bytes alignement + prBssidEx->u4Length = ALIGN_4(prBssidEx->u4Length); + + cp += prBssidEx->u4Length; + prList->u4NumberOfItems++; + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryBssidList */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScan ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_SSID_T prSsid; + PARAM_SSID_T rSsid; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(REQ, WARN, ("Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_SUCCESS; + } + + if(pvSetBuffer != NULL && u4SetBufferLen != 0) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + pvSetBuffer, + u4SetBufferLen); + prSsid = &rSsid; + } + else { + prSsid = NULL; + } + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)){ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED){ + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } + } + } + else +#endif + { + if(prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } + else if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScan */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScanExt ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_SCAN_REQUEST_EXT_T prScanRequest; + P_PARAM_SSID_T prSsid; + PUINT_8 pucIe; + UINT_32 u4IeLength; + + DEBUGFUNC("wlanoidSetBssidListScanExt()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if(u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(REQ, WARN, ("Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_SUCCESS; + } + + if(pvSetBuffer != NULL && u4SetBufferLen != 0) { + prScanRequest = (P_PARAM_SCAN_REQUEST_EXT_T)pvSetBuffer; + prSsid = &(prScanRequest->rSsid); + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + } + else { + prScanRequest = NULL; + prSsid = NULL; + pucIe = NULL; + u4IeLength = 0; + } + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)){ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED){ + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } + } + } + else +#endif + { + if(prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } + else if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanWithIE */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt to associate +* with the specified BSSID. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssid ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_UINT_8 pAddr; + UINT_32 i; + INT_32 i4Idx = -1; + P_MSG_AIS_ABORT_T prAisAbortMsg; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN;; + if (u4SetBufferLen != MAC_ADDR_LEN){ + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prGlueInfo = prAdapter->prGlueInfo; + pAddr = (P_UINT_8)pvSetBuffer; + + // re-association check + if(kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if(EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } + else { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + } + + // check if any scanned result matchs with the BSSID + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + if(EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32)i; + break; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS */ /* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + + if (EQUAL_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } + else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); + prAisAbortMsg->fgDelayIndication = FALSE; + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBssid() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt +* to associate with the new SSID. If the previous scanning +* result is aged, we will scan the channels at first. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSsid ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_SSID_T pParamSsid; + UINT_32 i; + INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN; + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if(prAdapter->fgIsRadioOff == TRUE) { + prAdapter->fgIsRadioOff = FALSE; + } + + if(u4SetBufferLen < sizeof(PARAM_SSID_T) || u4SetBufferLen > sizeof(PARAM_SSID_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + pParamSsid = (P_PARAM_SSID_T) pvSetBuffer; + + if (pParamSsid->u4SsidLen > 32) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + + // prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS + // re-association check + if(kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if(EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamSsid->aucSsid, + pParamSsid->u4SsidLen)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } + else { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + } + + // check if any scanned result matchs with the SSID + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if(EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, pParamSsid->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32)i; + i4MaxRSSI = i4RSSI; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS */ /* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamSsid->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if ( !((0 < pParamSsid->aucSsid[i]) && (pParamSsid->aucSsid[i] <= 0x1F)) ) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + + if(pParamSsid->u4SsidLen) { + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + } + else { + // wildcard SSID + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_ANY; + } + } + else { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + } + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + + if (EQUAL_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, + pParamSsid->aucSsid, + pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } + else { + /* Update the information to CONNECTION_SETTINGS_T */ + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, + pParamSsid->aucSsid, + (UINT_8)pParamSsid->u4SsidLen); + + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(SCN, INFO, ("SSID %s\n", prAdapter->rWifiVar.rConnSettings.aucSSID)); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the currently associated SSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySsid ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_SSID_T prAssociatedSsid; + + DEBUGFUNC("wlanoidQuerySsid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_SSID_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (P_PARAM_SSID_T)pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAssociatedSsid->u4SsidLen); + } + } + else { + prAssociatedSsid->u4SsidLen = 0; + + DBGLOG(REQ, TRACE, ("Null SSID\n")); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQuerySsid */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 network type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryInfrastructureMode ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *(P_ENUM_PARAM_OP_MODE_T)pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eOPMode; + + /* + ** According to OID_802_11_INFRASTRUCTURE_MODE + ** If there is no prior OID_802_11_INFRASTRUCTURE_MODE, + ** NDIS_STATUS_ADAPTER_NOT_READY shall be returned. + */ +#if DBG + switch (*(P_ENUM_PARAM_OP_MODE_T)pvQueryBuffer) { + case NET_TYPE_IBSS: + DBGLOG(REQ, INFO, ("IBSS mode\n")); + break; + case NET_TYPE_INFRA: + DBGLOG(REQ, INFO, ("Infrastructure mode\n")); + break; + default: + DBGLOG(REQ, INFO, ("Automatic mode\n")); + } +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryInfrastructureMode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set mode to infrastructure or +* IBSS, or automatic switch between the two. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid +* length of the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInfrastructureMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + ENUM_PARAM_OP_MODE_T eOpMode; + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set infrastructure mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eOpMode = *(P_ENUM_PARAM_OP_MODE_T)pvSetBuffer; + /* Verify the new infrastructure mode. */ + if (eOpMode >= NET_TYPE_NUM) { + DBGLOG(REQ, TRACE, ("Invalid mode value %d\n", eOpMode)); + return WLAN_STATUS_INVALID_DATA; + } + + /* check if possible to switch to AdHoc mode */ + if(eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) { + if(cnmAisIbssIsPermitted(prAdapter) == FALSE) { + DBGLOG(REQ, TRACE, ("Mode value %d unallowed\n", eOpMode)); + return WLAN_STATUS_FAILURE; + } + } + + /* Save the new infrastructure mode setting. */ + prAdapter->rWifiVar.rConnSettings.eOPMode = eOpMode; + + /* Clean up the Tx key flag */ + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; +#if CFG_SUPPORT_WAPI + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0; + kalMemZero(&prAdapter->prGlueInfo->aucWapiAssocInfoIEs, 42); +#endif + +#if CFG_SUPPORT_802_11W + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled = FALSE; +#endif + +#if CFG_SUPPORT_WPS2 + kalMemZero(&prAdapter->prGlueInfo->aucWSCAssocInfoIE, 200); + prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0; +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvSetBuffer, + u4SetBufferLen + ); + +} /* wlanoidSetInfrastructureMode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 authentication +* mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAuthMode ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(P_ENUM_PARAM_AUTH_MODE_T)pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if DBG + switch (*(P_ENUM_PARAM_AUTH_MODE_T)pvQueryBuffer) { + case AUTH_MODE_OPEN: + DBGLOG(REQ, INFO, ("Current auth mode: Open\n")); + break; + + case AUTH_MODE_SHARED: + DBGLOG(REQ, INFO, ("Current auth mode: Shared\n")); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(REQ, INFO, ("Current auth mode: Auto-switch\n")); + break; + + case AUTH_MODE_WPA: + DBGLOG(REQ, INFO, ("Current auth mode: WPA\n")); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(REQ, INFO, ("Current auth mode: WPA PSK\n")); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(REQ, INFO, ("Current auth mode: WPA None\n")); + break; + + case AUTH_MODE_WPA2: + DBGLOG(REQ, INFO, ("Current auth mode: WPA2\n")); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(REQ, INFO, ("Current auth mode: WPA2 PSK\n")); + break; + + default: + DBGLOG(REQ, INFO, ("Current auth mode: %d\n", + *(P_ENUM_PARAM_AUTH_MODE_T)pvQueryBuffer)); + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 authentication mode +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAuthMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4AkmSuite; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + /* RF Test */ + //if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { + // return WLAN_STATUS_SUCCESS; + //} + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_AUTH_MODE_T)pvSetBuffer >= AUTH_MODE_NUM) { + DBGLOG(REQ, TRACE, ("Invalid auth mode %d\n", + *(P_ENUM_PARAM_AUTH_MODE_T)pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_AUTH_MODE_T)pvSetBuffer) { + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + /* infrastructure mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA) { + return WLAN_STATUS_NOT_ACCEPTED; + } + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_IBSS) { + return WLAN_STATUS_NOT_ACCEPTED; + } + break; + + default: + ; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T)pvSetBuffer; + +#if DBG + switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_OPEN: + DBGLOG(RSN, TRACE, ("New auth mode: open\n")); + break; + + case AUTH_MODE_SHARED: + DBGLOG(RSN, TRACE, ("New auth mode: shared\n")); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(RSN, TRACE, ("New auth mode: auto-switch\n")); + break; + + case AUTH_MODE_WPA: + DBGLOG(RSN, TRACE, ("New auth mode: WPA\n")); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(RSN, TRACE, ("New auth mode: WPA PSK\n")); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(RSN, TRACE, ("New auth mode: WPA None\n")); + break; + + case AUTH_MODE_WPA2: + DBGLOG(RSN, TRACE, ("New auth mode: WPA2\n")); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(RSN, TRACE, ("New auth mode: WPA2 PSK\n")); + break; + + default: + DBGLOG(RSN, TRACE, ("New auth mode: unknown (%d)\n", + prAdapter->rWifiVar.rConnSettings.eAuthMode)); + } +#endif + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA) { + switch(prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_WPA: + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + + case AUTH_MODE_WPA_PSK: + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + + case AUTH_MODE_WPA_NONE: + u4AkmSuite = WPA_AKM_SUITE_NONE; + break; + + case AUTH_MODE_WPA2: + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + + case AUTH_MODE_WPA2_PSK: + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; + + default: + u4AkmSuite = 0; + } + } + else { + u4AkmSuite = 0; + } + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + } + else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; + } +#if CFG_SUPPORT_802_11W + if (kalGetMfpSetting(prAdapter->prGlueInfo) != RSN_AUTH_MFP_DISABLED) { + if ((u4AkmSuite == RSN_AKM_SUITE_PSK) && + prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_PSK_SHA256) { + DBGLOG(RSN, TRACE, ("Enable RSN_AKM_SUITE_PSK_SHA256 AKM support\n")); + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + + } + if ((u4AkmSuite == RSN_AKM_SUITE_802_1X) && + prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_802_1X_SHA256) { + DBGLOG(RSN, TRACE, ("Enable RSN_AKM_SUITE_802_1X_SHA256 AKM support\n")); + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + } + } +#endif + } + + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetAuthMode */ + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 privacy filter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPrivacyFilter ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(P_ENUM_PARAM_PRIVACY_FILTER_T)pvQueryBuffer = prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T)pvQueryBuffer) { + case PRIVACY_FILTER_ACCEPT_ALL: + DBGLOG(REQ, INFO, ("Current privacy mode: open mode\n")); + break; + + case PRIVACY_FILTER_8021xWEP: + DBGLOG(REQ, INFO, ("Current privacy mode: filtering mode\n")); + break; + + default: + DBGLOG(REQ, INFO, ("Current auth mode: %d\n", + *(P_ENUM_PARAM_AUTH_MODE_T)pvQueryBuffer)); + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPrivacyFilter */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 privacy filter +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPrivacyFilter ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_PRIVACY_FILTER_T)pvSetBuffer >= PRIVACY_FILTER_NUM) { + DBGLOG(REQ, TRACE, ("Invalid privacy filter %d\n", + *(P_ENUM_PARAM_PRIVACY_FILTER_T)pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T)pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = *(ENUM_PARAM_PRIVACY_FILTER_T)pvSetBuffer; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPrivacyFilter */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reload the available default settings for +* the specified type field. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetReloadDefaults ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + UINT_32 u4Len; + UINT_8 ucCmdSeqNum; + + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = sizeof(PARAM_RELOAD_DEFAULTS); + + //if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { + // return WLAN_STATUS_SUCCESS; + //} + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set Reload default! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + /* Verify the available reload options and reload the settings. */ + switch (*(P_PARAM_RELOAD_DEFAULTS)pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* Reload available default WEP keys from the permanent + storage. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = AUTH_MODE_OPEN; + prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT;//ENUM_ENCRYPTION_DISABLED; + { + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_802_11_KEY prCmdKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_802_11_KEY cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY)(prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8)prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = 0;//(UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); + kalMemCopy(prCmdKey->aucPeerAddr, aucBCAddr, MAC_ADDR_LEN); + + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); + + prCmdKey->ucKeyType = 0; + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(REQ, TRACE, ("Invalid reload option %d\n", + *(P_PARAM_RELOAD_DEFAULTS)pvSetBuffer)); + rStatus = WLAN_STATUS_INVALID_DATA; + } + + /* OID_802_11_RELOAD_DEFAULTS requiest to reset to auto mode */ + eNetworkType = PARAM_NETWORK_TYPE_AUTOMODE; + wlanoidSetNetworkTypeInUse(prAdapter, &eNetworkType, sizeof(eNetworkType), &u4Len); + + return rStatus; +} /* wlanoidSetReloadDefaults */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a WEP key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +#ifdef LINUX +UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN*/]; +UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif +WLAN_STATUS +wlanoidSetAddWep ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + #ifndef LINUX + UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN*/]; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + #endif + P_PARAM_WEP_T prNewWepKey; + P_PARAM_KEY_T prParamKey = (P_PARAM_KEY_T)keyBuffer; + UINT_32 u4KeyId, u4SetLen; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)) { + ASSERT(pu4SetInfoLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set add WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewWepKey = (P_PARAM_WEP_T)pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(REQ, WARN, ("Invalid total buffer length (%d) than minimum length (%d)\n", + (UINT_8)u4SetBufferLen, + (UINT_8)OFFSET_OF(PARAM_WEP_T, aucKeyMaterial))); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key structure length. */ + if (prNewWepKey->u4Length > u4SetBufferLen) { + DBGLOG(REQ, WARN, ("Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8)prNewWepKey->u4Length, + (UINT_8)u4SetBufferLen)); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key material length for maximum key material length:16 */ + if (prNewWepKey->u4KeyLength > 16 /* LEGACY_KEY_MAX_LEN */) { + DBGLOG(REQ, WARN, ("Invalid key material length (%d) greater than maximum key material length (16)\n", + (UINT_8)prNewWepKey->u4KeyLength)); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + + u4KeyId = prNewWepKey->u4KeyIndex & BITS(0,29) /* WEP_KEY_ID_FIELD */; + + /* Verify whether key index is valid or not, current version + driver support only 4 global WEP keys setting by this OID */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(REQ, ERROR, ("Error, invalid WEP key ID: %d\n", (UINT_8)u4KeyId)); + return WLAN_STATUS_INVALID_DATA; + } + + prParamKey->u4KeyIndex = u4KeyId; + + /* Transmit key */ + if (prNewWepKey->u4KeyIndex & IS_TRANSMIT_KEY) { + prParamKey->u4KeyIndex |= IS_TRANSMIT_KEY; + } + + /* Per client key */ + if (prNewWepKey->u4KeyIndex & IS_UNICAST_KEY) { + prParamKey->u4KeyIndex |= IS_UNICAST_KEY; + } + + prParamKey->u4KeyLength = prNewWepKey->u4KeyLength; + + kalMemCopy(prParamKey->arBSSID, aucBCAddr, MAC_ADDR_LEN); + + kalMemCopy(prParamKey->aucKeyMaterial, + prNewWepKey->aucKeyMaterial, + prNewWepKey->u4KeyLength); + + prParamKey->u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, + (PVOID)prParamKey, + prParamKey->u4Length, + &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddWep */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the WEP key +* at the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveWep ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + UINT_32 u4KeyId, u4SetLen; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_KEY_INDEX); + + if (u4SetBufferLen < sizeof(PARAM_KEY_INDEX)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + u4KeyId = *(PUINT_32)pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(REQ, INFO, ("Set: Dump PARAM_KEY_INDEX content\n")); + DBGLOG(REQ, INFO, ("Index : 0x%08lx\n", u4KeyId)); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set remove WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4KeyId & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, ("Invalid WEP key index: 0x%08lx\n", u4KeyId)); + return WLAN_STATUS_INVALID_DATA; + } + + u4KeyId &= BITS(0,7); + + /* Verify whether key index is valid or not. Current version + driver support only 4 global WEP keys. */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(REQ, ERROR, ("invalid WEP key ID %lu\n", u4KeyId)); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + rRemoveKey.u4KeyIndex = *(PUINT_32)pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, + (PVOID)&rRemoveKey, + sizeof(PARAM_REMOVE_KEY_T), + &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveWep */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddKey ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(REQ, WARN, ("Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8)prNewKey->u4Length, + (UINT_8)u4SetBufferLen)); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(REQ, WARN, ("Invalid key material length (%d)\n", (UINT_8)prNewKey->u4KeyLength)); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) { + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30,31)) == IS_UNICAST_KEY) { + return WLAN_STATUS_INVALID_DATA; + } + + if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || + prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) + { + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30,31)) == BITS(30,31)) { + if (((prNewKey->u4KeyIndex & 0xff) != 0) || + ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) && + (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) && (prNewKey->arBSSID[5] == 0xff))) { + return WLAN_STATUS_INVALID_DATA; + } + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Dump PARAM_KEY content. */ + DBGLOG(REQ, TRACE, ("Set: Dump PARAM_KEY content\n")); + DBGLOG(REQ, TRACE, ("Length : 0x%08lx\n", prNewKey->u4Length)); + DBGLOG(REQ, TRACE, ("Key Index : 0x%08lx\n", prNewKey->u4KeyIndex)); + DBGLOG(REQ, TRACE, ("Key Length: 0x%08lx\n", prNewKey->u4KeyLength)); + DBGLOG(REQ, TRACE, ("BSSID:\n")); + DBGLOG_MEM8(REQ, TRACE, prNewKey->arBSSID, sizeof(PARAM_MAC_ADDRESS)); + DBGLOG(REQ, TRACE, ("Key RSC:\n")); + DBGLOG_MEM8(REQ, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + DBGLOG(REQ, TRACE, ("Key Material:\n")); + DBGLOG_MEM8(REQ, TRACE, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + /* Todo:: Store the legacy wep key for OID_802_11_RELOAD_DEFAULTS */ + } + + if (prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = TRUE; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, INFO, ("ucCmdSeqNum = %d\n", ucCmdSeqNum)); + + // compose CMD_802_11_KEY cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY)(prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + prCmdKey->ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; + prCmdKey->ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + prCmdKey->ucIsAuthenticator = ((prNewKey->u4KeyIndex & IS_AUTHENTICATOR) == IS_AUTHENTICATOR) ? 1 : 0; + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8)prNewKey->arBSSID, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = (UINT_8)(prNewKey->u4KeyIndex & 0xff); + + /* Note: adjust the key length for WPA-None */ + prCmdKey->ucKeyLen = (UINT_8)prNewKey->u4KeyLength; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8)prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + + if (prNewKey->u4KeyLength == 5) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP40; + } + else if (prNewKey->u4KeyLength == 13) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP104; + } + else if (prNewKey->u4KeyLength == 16) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP128; + else { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } + else +#endif + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + } + } + else if (prNewKey->u4KeyLength == 32) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = CCMP_KEY_LEN; + } + } + else { + if (rsnCheckPmkidCandicate(prAdapter)) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + DBGLOG(RSN, TRACE, ("Add key: Prepare a timer to indicate candidate PMKID Candidate\n")); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddKey */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the key at +* the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveKey ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_REMOVE_KEY_T prRemovedKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set remove key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T)pvSetBuffer; + + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(REQ, INFO, ("Set: Dump PARAM_REMOVE_KEY content\n")); + DBGLOG(REQ, INFO, ("Length : 0x%08lx\n", prRemovedKey->u4Length)); + DBGLOG(REQ, INFO, ("Key Index : 0x%08lx\n", prRemovedKey->u4KeyIndex)); + DBGLOG(REQ, INFO, ("BSSID:\n")); + DBGLOG_MEM8(REQ, INFO, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, ("invalid key index: 0x%08lx\n", + prRemovedKey->u4KeyIndex)); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, ("invalid key index: 0x%08lx\n", + prRemovedKey->u4KeyIndex)); + return WLAN_STATUS_INVALID_DATA; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + } + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_802_11_KEY cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY)(prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8)prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8)prRemovedKey->arBSSID, MAC_ADDR_LEN); + +#if CFG_SUPPORT_802_11W + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM + 2); +#else + //ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); +#endif + + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + prCmdKey->ucKeyType = 1; + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveKey */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current encryption status. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEncryptionStatus ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + BOOLEAN fgTransmitKeyAvailable = TRUE; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus = 0; + + DEBUGFUNC("wlanoidQueryEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + fgTransmitKeyAvailable = prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist; + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } + else { + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + } + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + else { + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + } + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } + else { + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + } + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(REQ, ERROR, ("Unknown Encryption Status Setting:%d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus)); + } + +#if DBG + DBGLOG(REQ, INFO, + ("Encryption status: %d Return:%d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus, + eEncStatus)); +#endif + + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T)pvQueryBuffer = eEncStatus; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryEncryptionStatus */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the encryption status to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_SUPPORTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEncryptionStatus ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_ENCRYPTION_STATUS_T eEewEncrypt; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + //if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { + // return WLAN_STATUS_SUCCESS; + //} + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set encryption status! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eEewEncrypt = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T)pvSetBuffer; + DBGLOG(REQ, TRACE, ("ENCRYPTION_STATUS %d\n", eEewEncrypt)); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, TRACE, ("Disable Encryption\n")); + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ + DBGLOG(RSN, TRACE, ("Enable Encryption1\n")); + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128 | + CIPHER_FLAG_TKIP); + DBGLOG(RSN, TRACE, ("Enable Encryption2\n")); + break; + + case ENUM_ENCRYPTION3_ENABLED: /* Enable WEP, TKIP, AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128 | + CIPHER_FLAG_TKIP | + CIPHER_FLAG_CCMP); + DBGLOG(RSN, TRACE, ("Enable Encryption3\n")); + break; + + default: + DBGLOG(RSN, WARN, ("Unacceptible encryption status: %d\n", + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T)pvSetBuffer)); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T)pvSetBuffer; + } + + return rStatus; +} /* wlanoidSetEncryptionStatus */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to test the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTest ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_802_11_TEST_T prTest; + PVOID pvTestData; + PVOID pvStatusBuffer; + UINT_32 u4StatusBufferSize; + + DEBUGFUNC("wlanoidSetTest"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + + prTest = (P_PARAM_802_11_TEST_T)pvSetBuffer; + + DBGLOG(REQ, TRACE, ("Test - Type %ld\n", prTest->u4Type)); + + switch (prTest->u4Type) { + case 1: /* Type 1: generate an authentication event */ + pvTestData = (PVOID)&prTest->u.AuthenticationEvent; + pvStatusBuffer = (PVOID)prAdapter->aucIndicationEventBuffer; + u4StatusBufferSize = prTest->u4Length - 8; + break; + + case 2: /* Type 2: generate an RSSI status indication */ + pvTestData = (PVOID)&prTest->u.RssiTrigger; + pvStatusBuffer = (PVOID)&prAdapter->rWlanInfo.rCurrBssId.rRssi; + u4StatusBufferSize = sizeof(PARAM_RSSI); + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + ASSERT(u4StatusBufferSize <= 180); + if (u4StatusBufferSize > 180) { + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Get the contents of the StatusBuffer from the test structure. */ + kalMemCopy(pvStatusBuffer, pvTestData, u4StatusBufferSize); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + pvStatusBuffer, + u4StatusBufferSize); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetTest */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the driver's WPA2 status. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCapability ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CAPABILITY_T prCap; + P_PARAM_AUTH_ENCRYPTION_T prAuthenticationEncryptionSupported; + + DEBUGFUNC("wlanoidQueryCapability"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = 4 * sizeof(UINT_32) + 14 * sizeof(PARAM_AUTH_ENCRYPTION_T); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prCap = (P_PARAM_CAPABILITY_T)pvQueryBuffer; + + prCap->u4Length = *pu4QueryInfoLen; + prCap->u4Version = 2; /* WPA2 */ + prCap->u4NoOfPMKIDs = CFG_MAX_PMKID_CACHE; + prCap->u4NoOfAuthEncryptPairsSupported = 14; + + prAuthenticationEncryptionSupported = + &prCap->arAuthenticationEncryptionSupported[0]; + + // fill 14 entries of supported settings + prAuthenticationEncryptionSupported[0].eAuthModeSupported = + AUTH_MODE_OPEN; + + prAuthenticationEncryptionSupported[0].eEncryptStatusSupported = + ENUM_ENCRYPTION_DISABLED; + + prAuthenticationEncryptionSupported[1].eAuthModeSupported = + AUTH_MODE_OPEN; + prAuthenticationEncryptionSupported[1].eEncryptStatusSupported = + ENUM_ENCRYPTION1_ENABLED; + + prAuthenticationEncryptionSupported[2].eAuthModeSupported = + AUTH_MODE_SHARED; + prAuthenticationEncryptionSupported[2].eEncryptStatusSupported = + ENUM_ENCRYPTION_DISABLED; + + prAuthenticationEncryptionSupported[3].eAuthModeSupported = + AUTH_MODE_SHARED; + prAuthenticationEncryptionSupported[3].eEncryptStatusSupported = + ENUM_ENCRYPTION1_ENABLED; + + prAuthenticationEncryptionSupported[4].eAuthModeSupported = + AUTH_MODE_WPA; + prAuthenticationEncryptionSupported[4].eEncryptStatusSupported = + ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[5].eAuthModeSupported = + AUTH_MODE_WPA; + prAuthenticationEncryptionSupported[5].eEncryptStatusSupported = + ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[6].eAuthModeSupported = + AUTH_MODE_WPA_PSK; + prAuthenticationEncryptionSupported[6].eEncryptStatusSupported = + ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[7].eAuthModeSupported = + AUTH_MODE_WPA_PSK; + prAuthenticationEncryptionSupported[7].eEncryptStatusSupported = + ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[8].eAuthModeSupported = + AUTH_MODE_WPA_NONE; + prAuthenticationEncryptionSupported[8].eEncryptStatusSupported = + ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[9].eAuthModeSupported = + AUTH_MODE_WPA_NONE; + prAuthenticationEncryptionSupported[9].eEncryptStatusSupported = + ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[10].eAuthModeSupported = + AUTH_MODE_WPA2; + prAuthenticationEncryptionSupported[10].eEncryptStatusSupported = + ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[11].eAuthModeSupported = + AUTH_MODE_WPA2; + prAuthenticationEncryptionSupported[11].eEncryptStatusSupported = + ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[12].eAuthModeSupported = + AUTH_MODE_WPA2_PSK; + prAuthenticationEncryptionSupported[12].eEncryptStatusSupported = + ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[13].eAuthModeSupported = + AUTH_MODE_WPA2_PSK; + prAuthenticationEncryptionSupported[13].eEncryptStatusSupported = + ENUM_ENCRYPTION3_ENABLED; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryCapability */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the PMKID in the PMK cache. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPmkid ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + UINT_32 i; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidQueryPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + *pu4QueryInfoLen = OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo) + + prAisSpecBssInfo->u4PmkidCacheCount * sizeof(PARAM_BSSID_INFO_T); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prPmkid = (P_PARAM_PMKID_T)pvQueryBuffer; + + prPmkid->u4Length = *pu4QueryInfoLen; + prPmkid->u4BSSIDInfoCount = prAisSpecBssInfo->u4PmkidCacheCount; + + for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { + kalMemCopy(prPmkid->arBSSIDInfo[i].arBSSID, + prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, + sizeof(PARAM_MAC_ADDRESS)); + kalMemCopy(prPmkid->arBSSIDInfo[i].arPMKID, + prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arPMKID, + sizeof(PARAM_PMKID_VALUE)); + } + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryPmkid */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the PMKID to the PMK cache in the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPmkid ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + UINT_32 i, j; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidSetPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = u4SetBufferLen; + + /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean PMKID */ + if (u4SetBufferLen < OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(pvSetBuffer); + prPmkid = (P_PARAM_PMKID_T)pvSetBuffer; + + if (u4SetBufferLen < + ((prPmkid->u4BSSIDInfoCount * sizeof(PARAM_BSSID_INFO_T)) + + OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo))) { + return WLAN_STATUS_INVALID_DATA; + } + + if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) { + return WLAN_STATUS_INVALID_DATA; + } + + DBGLOG(REQ, INFO, ("Count %lu\n", prPmkid->u4BSSIDInfoCount)); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + + /* + The driver can only clear its PMKID cache whenever it make a media disconnect + indication. Otherwise, it must change the PMKID cache only when set through this OID. + */ +#if CFG_RSN_MIGRATION + for (i = 0; i < prPmkid->u4BSSIDInfoCount; i++) { + /* Search for desired BSSID. If desired BSSID is found, + then set the PMKID */ + if (!rsnSearchPmkidEntry(prAdapter, + (PUINT_8)prPmkid->arBSSIDInfo[i].arBSSID, + &j)) { + /* No entry found for the specified BSSID, so add one entry */ + if (prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE - 1) { + j = prAisSpecBssInfo->u4PmkidCacheCount; + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[i].arBSSID, + sizeof(PARAM_MAC_ADDRESS)); + prAisSpecBssInfo->u4PmkidCacheCount++; + } + else { + j = CFG_MAX_PMKID_CACHE; + } + } + + if (j < CFG_MAX_PMKID_CACHE) { + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[i].arPMKID, + sizeof(PARAM_PMKID_VALUE)); + DBGLOG(RSN, TRACE, ("Add BSSID "MACSTR" idx=%d PMKID value "MACSTR"\n", + MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID),j, MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID))); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } +#endif + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPmkid */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the set of supported data rates that +* the radio is capable of running +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query +* \param[in] u4QueryBufferLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number +* of bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySupportedRates ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + PARAM_RATES eRate = { + // BSSBasicRateSet for 802.11n Non-HT rates + 0x8C, // 6M + 0x92, // 9M + 0x98, // 12M + 0xA4, // 18M + 0xB0, // 24M + 0xC8, // 36M + 0xE0, // 48M + 0xEC // 54M + }; + + DEBUGFUNC("wlanoidQuerySupportedRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen ) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, + (PVOID)&eRate, + sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQuerySupportedRates() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryDesiredRates ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen ) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, + (PVOID)&(prAdapter->rWlanInfo.eDesiredRates), + sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryDesiredRates() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDesiredRates ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + UINT_32 i; + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(PARAM_RATES); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy((PVOID)&(prAdapter->rWlanInfo.eDesiredRates), + pvSetBuffer, + sizeof(PARAM_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; + for (i = 0 ; i < PARAM_MAX_LEN_RATES ; i++) { + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = + (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8)&(prAdapter->rWlanInfo.eLinkAttr), + pvSetBuffer, + u4SetBufferLen + ); + +} /* end of wlanoidSetDesiredRates() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum frame size in bytes, +* not including the header. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxFrameSize ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32)pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxFrameSize */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum total packet length +* in bytes. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxTotalSize ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32)pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxTotalSize */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the vendor ID of the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryVendorId ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ +#if DBG + PUINT_8 cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((PUINT_8)pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(UINT_32); + +#if DBG + cp = (PUINT_8)pvQueryBuffer; + DBGLOG(REQ, LOUD, ("Vendor ID=%02x-%02x-%02x-%02x\n", cp[0], cp[1], cp[2], cp[3])); +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryVendorId */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssi ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, ("Too short length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (prAdapter->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI)prAdapter->rLinkQuality.cRssi; // ranged from (-128 ~ 30) in unit of dBm + + if(rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if(rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } + + #ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, + pvQueryBuffer, + pvQueryBuffer, + u4QueryBufferLen + ); + #else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + + #endif +} /* end of wlanoidQueryRssi() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI trigger value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssiTrigger ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + + if(prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_NONE) + return WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, ("Too short length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(REQ, INFO, ("RSSI trigger: %ld dBm\n", *(PARAM_RSSI *) pvQueryBuffer)); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRssiTrigger */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a trigger value of the RSSI event. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRssiTrigger ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PARAM_RSSI rRssiTriggerValue; + DEBUGFUNC("wlanoidSetRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + + *pu4SetInfoLen = sizeof(PARAM_RSSI); + rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; + + if(rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM + || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) + return + + /* Save the RSSI trigger value to the Adapter structure */ + prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; + + /* If the RSSI trigger value is equal to the current RSSI value, the + * indication triggers immediately. We need to indicate the protocol + * that an RSSI status indication event triggers. */ + if (rRssiTriggerValue == (PARAM_RSSI)(prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); + } + else if(rRssiTriggerValue < (PARAM_RSSI)(prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; + else if(rRssiTriggerValue > (PARAM_RSSI)(prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetRssiTrigger */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a suggested value for the number of +* bytes of received packet data that will be indicated to the protocol +* driver. We just accept the set and ignore this value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentLookahead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* receives but does not indicate to the protocols due to errors. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRcvError"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + // @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvError, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryRcvError */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* cannot receive due to lack of NIC receive buffer space. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvNoBuffer ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRcvNoBuffer"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) 0; //@FIXME + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) 0; //@FIXME + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvNoBuffer, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryRcvNoBuffer */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* received and it is CRC error. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvCrcError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRcvCrcError"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvCrcError, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryRcvCrcError */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStatistics ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(REQ, WARN, ("Too short length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount + = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount + = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount + = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount + = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount + = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount + = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount + = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount + = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount + = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount + = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount + = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount + = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart + = 0; + prStatistics->rTKIPICVErrors.QuadPart + = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart + = 0; + prStatistics->rTKIPReplays.QuadPart + = 0; + prStatistics->rCCMPFormatErrors.QuadPart + = 0; + prStatistics->rCCMPReplays.QuadPart + = 0; + prStatistics->rCCMPDecryptErrors.QuadPart + = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart + = 0; + prStatistics->rWEPUndecryptableCount.QuadPart + = 0; + prStatistics->rWEPICVErrorCount.QuadPart + = 0; + prStatistics->rDecryptSuccessCount.QuadPart + = 0; + prStatistics->rDecryptFailureCount.QuadPart + = 0; + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryStatistics */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query current media streaming status. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen ) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(P_ENUM_MEDIA_STREAM_MODE)pvQueryBuffer = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? + ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to enter media streaming mode or exit media streaming mode +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE)pvSetBuffer; + + if(eStreamMode == ENUM_MEDIA_STREAM_OFF) + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + else + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetMediaStreamMode, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8)&(prAdapter->rWlanInfo.eLinkAttr), + pvSetBuffer, + u4SetBufferLen + ); +} /* wlanoidSetMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the permanent MAC address of the NIC. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPermanentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryPermanentAddr"); + DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucPermanentAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPermanentAddr */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidQueryCurrentAddr"); + DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryAddress, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), + (PUINT_8)&rCmdBasicConfig, + pvQueryBuffer, + u4QueryBufferLen + ); + +} /* wlanoidQueryCurrentAddr */ + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query NIC link speed. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + *(PUINT_32)pvQueryBuffer = 10000; // change to unit of 100bps + return WLAN_STATUS_SUCCESS; + } + else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + *(PUINT_32)pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; // change to unit of 100bps + return WLAN_STATUS_SUCCESS; + } + else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* end of wlanoidQueryLinkSpeed() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query MCR value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMcrRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CUSTOM_MCR_RW_STRUC_T prMcrRdInfo; + CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_T)pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if((prMcrRdInfo->u4McrOffset >>16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_READ, + (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0,15)), + &prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000*/ + if (prMcrRdInfo->u4McrOffset & 0xFFFF0000){ + // fill command + rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; + rCmdAccessReg.u4Data = 0; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcrRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvQueryBuffer, + u4QueryBufferLen + ); + } + else { + HAL_MCR_RD(prAdapter, + prMcrRdInfo->u4McrOffset & BITS(2,31), //address is in DWORD unit + &prMcrRdInfo->u4McrData); + + DBGLOG(INIT, TRACE, ("MCR Read: Offset = %#08lx, Data = %#08lx\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData)); + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMcrWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_MCR_RW_STRUC_T prMcrWrInfo; + CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + P_STA_RECORD_T prStaRec = prBssInfo->prStaRecOfAP; + UINT_32 u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_T)pvSetBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + + // -- Puff Stress Test Begin +#if CFG_STRESS_TEST_SUPPORT + + // 0xFFFFFFFE for Control Rate + if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE){ + if(prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0){ + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T)(prMcrWrInfo->u4McrData); + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); + DBGLOG(INIT, TRACE, ("[Stress Test] Rate is Changed to index %d...\n", prAdapter->rWifiVar.eRateSetting)); + } + + // 0xFFFFFFFD for Switch Channel + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFD){ + if(prMcrWrInfo->u4McrData <= 11 && prMcrWrInfo->u4McrData >= 1){ + prBssInfo->ucPrimaryChannel = prMcrWrInfo->u4McrData; + } + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + DBGLOG(INIT, TRACE, ("[Stress Test] Channel is switched to %d ...\n", prBssInfo->ucPrimaryChannel)); + + return WLAN_STATUS_SUCCESS; + } + + // 0xFFFFFFFFC for Control RF Band and SCO + else if(prMcrWrInfo->u4McrOffset == 0xFFFFFFFC){ + // Band + if(prMcrWrInfo->u4McrData & 0x80000000){ + //prBssInfo->eBand = BAND_5G; + //prBssInfo->ucPrimaryChannel = 52; // Bond to Channel 52 + } else { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 8; // Bond to Channel 6 + } + + // Bandwidth + if(prMcrWrInfo->u4McrData & 0x00010000){ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + if(prMcrWrInfo->u4McrData == 0x00010002){ + prBssInfo->eBssSCO = CHNL_EXT_SCB; // U20 + prBssInfo->ucPrimaryChannel += 2; + } else if (prMcrWrInfo->u4McrData == 0x00010001){ + prBssInfo->eBssSCO = CHNL_EXT_SCA; // L20 + prBssInfo->ucPrimaryChannel -= 2; + } else { + prBssInfo->eBssSCO = CHNL_EXT_SCA; // 40 + } + } + + if(prMcrWrInfo->u4McrData & 0x00000000){ + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + } + + // 0xFFFFFFFB for HT Capability + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFB){ + /* Enable HT Capability */ + if(prMcrWrInfo->u4McrData & 0x00000001){ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + DEBUGFUNC("[Stress Test]Enable HT capability...\n"); + }else{ + prStaRec->u2HtCapInfo &= (~HT_CAP_INFO_HT_GF); + DEBUGFUNC("[Stress Test]Disable HT capability...\n"); + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } + + // 0xFFFFFFFA for Enable Random Rx Reset + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFA){ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd( + prAdapter, + CMD_ID_RANDOM_RX_RESET_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + + // 0xFFFFFFF9 for Disable Random Rx Reset + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF9){ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd( + prAdapter, + CMD_ID_RANDOM_RX_RESET_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + + // 0xFFFFFFF8 for Enable SAPP + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF8){ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd( + prAdapter, + CMD_ID_SAPP_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + + // 0xFFFFFFF7 for Disable SAPP + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF7){ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd( + prAdapter, + CMD_ID_SAPP_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + + else +#endif + // -- Puff Stress Test End + + + /* Check if access F/W Domain MCR */ + if (prMcrWrInfo->u4McrOffset & 0xFFFF0000){ + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if((prMcrWrInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_WRITE, + (UINT_16) (prMcrWrInfo->u4McrOffset & BITS(0,15)), + &prMcrWrInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + + #if 1 + // low power test special command + if (prMcrWrInfo->u4McrOffset == 0x11111110){ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + //DbgPrint("Enter test mode\n"); + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111){ + //DbgPrint("nicpmSetAcpiPowerD3\n"); + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32)ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112){ + + //DbgPrint("LP enter sleep\n"); + + // fill command + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } +#endif + + #if 1 + // low power test special command + if (prMcrWrInfo->u4McrOffset == 0x11111110){ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + //DbgPrint("Enter test mode\n"); + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111){ + //DbgPrint("nicpmSetAcpiPowerD3\n"); + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32)ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112){ + + //DbgPrint("LP enter sleep\n"); + + // fill command + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + +#endif + // fill command + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + u4SetBufferLen + ); + } + else { + HAL_MCR_WR(prAdapter, + (prMcrWrInfo->u4McrOffset & BITS(2,31)), //address is in DWORD unit + prMcrWrInfo->u4McrData); + + DBGLOG(INIT, TRACE, ("MCR Write: Offset = %#08lx, Data = %#08lx\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData)); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query SW CTRL +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySwCtrlRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUC_T prSwCtrlInfo; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_T)pvQueryBuffer; + + u2Id = (UINT_16)(prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16)(prSwCtrlInfo->u4Id & BITS(0,15)); + u4Data = 0; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch(u2Id) { + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, + SWCR_READ/* Read */, + (UINT_16) u2SubId , + &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: + { + u4Data = 0x5AA56620; + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + TRUE, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvQueryBuffer, + u4QueryBufferLen + ); + } + } /* switch(u2Id)*/ + + prSwCtrlInfo->u4Data = u4Data; + + return rWlanStatus; + +} + /* end of wlanoidQuerySwCtrlRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write SW CTRL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSwCtrlWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUC_T prSwCtrlInfo; + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_T)pvSetBuffer; + + u2Id = (UINT_16)(prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16)(prSwCtrlInfo->u4Id & BITS(0,15)); + u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch(u2Id) { + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, + SWCR_WRITE, + (UINT_16) u2SubId, + &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0x1000: + if (u2SubId == 0x8000) { + // CTIA power save mode setting (code: 0x10008000) + prAdapter->u4CtiaPowerMode = u4Data; + prAdapter->fgEnCtiaPowerMode = TRUE; + + // + { + PARAM_POWER_MODE ePowerMode; + + if (prAdapter->u4CtiaPowerMode == 0) { + // force to keep in CAM mode + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else { + ePowerMode = Param_PowerModeFast_PSP; + } + + nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_AIS_INDEX, + ePowerMode, + TRUE); + } + } + break; + case 0x1001: + if(u2SubId == 0x0) { + prAdapter->fgEnOnlineScan = (BOOLEAN)u4Data; + } + else if(u2SubId == 0x1) { + prAdapter->fgDisBcnLostDetection = (BOOLEAN)u4Data; + } + else if(u2SubId == 0x2) { + prAdapter->rWifiVar.fgSupportUAPSD = (BOOLEAN)u4Data; + } + else if(u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0,15); + prAdapter->rWifiVar.arBssInfo[u4Data>>16].rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8)prAdapter->u4UapsdAcBmp; + prAdapter->rWifiVar.arBssInfo[u4Data>>16].rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8)prAdapter->u4UapsdAcBmp; + } + else if(u2SubId == 0x4) { + prAdapter->fgDisStaAgingTimeoutDetection = (BOOLEAN)u4Data; + } + else if(u2SubId == 0x5) { + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = (UINT_8)u4Data; + } + + + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: + if(u2SubId == 0x0) { + if (u4Data) { + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + } + swCrFrameCheckEnable(prAdapter, u4Data); + } + else if(u2SubId == 0x1) { + BOOLEAN fgIsEnable; + UINT_8 ucType; + UINT_32 u4Timeout; + + fgIsEnable = (BOOLEAN)(u4Data & 0xff); + ucType = 0;//((u4Data>>4) & 0xf); + u4Timeout = ((u4Data>>8) & 0xff); + swCrDebugCheckEnable(prAdapter, fgIsEnable, ucType, u4Timeout); + } + break; +#endif + +#if CFG_SUPPORT_802_11W + case 0x2000: + DBGLOG(RSN, INFO, ("802.11w test 0x%x\n", u2SubId)); + if (u2SubId == 0x0) { + rsnStartSaQuery(prAdapter); + } + if (u2SubId == 0x1) { + rsnStopSaQuery(prAdapter); + } + if (u2SubId == 0x2) { + rsnSaQueryRequest(prAdapter, NULL); + } + if (u2SubId == 0x3) { + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + authSendDeauthFrame(prAdapter, prBssInfo->prStaRecOfAP , NULL, 7, NULL); + } + /* wext_set_mode */ + /* + if (u2SubId == 0x3) { + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_DISABLED; + } + if (u2SubId == 0x4) { + //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_OPTIONAL; + } + if (u2SubId == 0x5) { + //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_REQUIRED; + } + */ + break; +#endif + case 0xFFFF: + { + CMD_ACCESS_REG rCmdAccessReg; +#if 1 //CFG_MT6573_SMT_TEST + if (u2SubId == 0x0123) { + + DBGLOG(HAL, INFO, ("set smt fixed rate: %d \n", u4Data)); + + if((ENUM_REGISTRY_FIXED_RATE_T)(u4Data) < FIXED_RATE_NUM) { + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T)(u4Data); + } + else { + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + } + + if(prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) { + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + } + else if((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) { + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + } + else { + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + } + + /* abort to re-connect */ +#if 1 + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } + else if (u2SubId == 0x1234) { + // 1. Disable On-Lin Scan + prAdapter->fgEnOnlineScan = FALSE; + + // 3. Disable FIFO FULL no ack + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x904; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, //FALSE, + FALSE, //TRUE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + 0 + ); + + // 4. Disable Roaming + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + // Disalbe auto tx power + // + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + + + // 2. Keep at CAM mode + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_AIS_INDEX, + ePowerMode, + TRUE); + } + + // 5. Disable Beacon Timeout Detection + prAdapter->fgDisBcnLostDetection = TRUE; + } + else if (u2SubId == 0x1235) { + + // 1. Enaable On-Lin Scan + prAdapter->fgEnOnlineScan = TRUE; + + // 3. Enable FIFO FULL no ack + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x905; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, //FALSE, + FALSE, //TRUE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + pvSetBuffer, + 0 + ); + + // 4. Enable Roaming + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + // Enable auto tx power + // + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + + + // 2. Keep at Fast PS + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_AIS_INDEX, + ePowerMode, + TRUE); + } + + // 5. Enable Beacon Timeout Detection + prAdapter->fgDisBcnLostDetection = FALSE; + } +#endif + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, + pvSetBuffer, + u4SetBufferLen + ); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} + /* wlanoidSetSwCtrlWrite */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query EEPROM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUC_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_T)pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8)&rCmdAccessEeprom, + pvQueryBuffer, + u4QueryBufferLen + ); + +} /* wlanoidQueryEepromRead */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write EEPROM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEepromWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUC_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8)&rCmdAccessEeprom, + pvSetBuffer, + u4SetBufferLen + ); + +} /* wlanoidSetEepromWrite */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully transmitted +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOk ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryXmitOk"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOk, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryXmitOk */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully received +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvOk ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRcvOk"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvOk, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryRcvOk */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* fails to transmit. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryXmitError"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitError, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryXmitError */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after exactly one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOneCollision ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryXmitOneCollision"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - prAdapter->rStatStruct.rRetryCount.QuadPart); + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - prAdapter->rStatStruct.rRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOneCollision, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryXmitOneCollision */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after more than one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMoreCollisions ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryXmitMoreCollisions"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMoreCollisions, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryXmitMoreCollisions */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames +* not transmitted due to excessive collisions. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMaxCollisions ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryXmitMaxCollisions"); + DBGLOG(REQ, LOUD, ("\n")); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if(IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if(u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } + else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMaxCollisions, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + } +} /* wlanoidQueryXmitMaxCollisions */ + + +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 // for WPDWifi DLL +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current the OID interface version, +* which is the interface between the application and driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryOidInterfaceVersion ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + *(PUINT_32) pvQueryBuffer = MTK_CUSTOM_OID_INTERFACE_VERSION ; + *pu4QueryInfoLen = sizeof(UINT_32); + + DBGLOG(REQ, WARN, ("Custom OID interface version: %#08lX\n", + *(PUINT_32) pvQueryBuffer)); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryOidInterfaceVersion */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMulticastList( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ +#ifndef LINUX + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcastAddr, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); +#else + return WLAN_STATUS_SUCCESS; +#endif +} /* end of wlanoidQueryMulticastList() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ + WLAN_STATUS + wlanoidSetMulticastList( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) + { + UINT_8 ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Caller should provide this information */ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, ("Invalid MC list length %ld\n", u4SetBufferLen)); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / + MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { + DBGLOG(REQ, WARN, ("Too many MC addresses\n")); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) { + ASSERT(pvSetBuffer); + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = ucNetTypeIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8)&rCmdMacMcastAddr, + pvSetBuffer, + u4SetBufferLen + ); +} /* end of wlanoidSetMulticastList() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentPacketFilter ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + UINT_32 u4NewPacketFilter; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetCurrentPacketFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pvSetBuffer); + + /* Set the new packet filter. */ + u4NewPacketFilter = *(PUINT_32) pvSetBuffer; + + DBGLOG(REQ, INFO, ("New packet filter: %#08lx\n", u4NewPacketFilter)); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set current packet filter! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + do { + /* Verify the bits of the new packet filter. If any bits are set that + we don't support, leave. */ + if (u4NewPacketFilter & ~(PARAM_PACKET_FILTER_SUPPORTED)) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + } + +#if DBG + /* Need to enable or disable promiscuous support depending on the new + filter. */ + if (u4NewPacketFilter & PARAM_PACKET_FILTER_PROMISCUOUS) { + DBGLOG(REQ, INFO, ("Enable promiscuous mode\n")); + } + else { + DBGLOG(REQ, INFO, ("Disable promiscuous mode\n")); + } + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) { + DBGLOG(REQ, INFO, ("Enable all-multicast mode\n")); + } + else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + DBGLOG(REQ, INFO, ("Enable multicast\n")); + } + else { + DBGLOG(REQ, INFO, ("Disable multicast\n")); + } + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) { + DBGLOG(REQ, INFO, ("Enable Broadcast\n")); + } + else { + DBGLOG(REQ, INFO, ("Disable Broadcast\n")); + } +#endif + } while (FALSE); + + if(rStatus == WLAN_STATUS_SUCCESS) { + // Store the packet filter + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8)&prAdapter->u4OsPacketFilter, + pvSetBuffer, + u4SetBufferLen + ); + } + else { + return rStatus; + } +} /* wlanoidSetCurrentPacketFilter */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current packet filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentPacketFilter ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen >= sizeof(UINT_32)) { + ASSERT(pvQueryBuffer); + *(PUINT_32) pvQueryBuffer = prAdapter->u4OsPacketFilter; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryCurrentPacketFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query ACPI device power state. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ +#if DBG + PPARAM_DEVICE_POWER_STATE prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvQueryBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(REQ, INFO, ("Query Power State: D0\n")); + break; + case ParamDeviceStateD1: + DBGLOG(REQ, INFO, ("Query Power State: D1\n")); + break; + case ParamDeviceStateD2: + DBGLOG(REQ, INFO, ("Query Power State: D2\n")); + break; + case ParamDeviceStateD3: + DBGLOG(REQ, INFO, ("Query Power State: D3\n")); + break; + default: + break; + } +#endif + + /* Since we will disconnect the newwork, therefore we do not + need to check queue empty */ + *(PPARAM_DEVICE_POWER_STATE) pvQueryBuffer = ParamDeviceStateD3; + //WARNLOG(("Ready to transition to D3\n")); + return WLAN_STATUS_SUCCESS; + +} /* pwrmgtQueryPower */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set ACPI device power state. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAcpiDevicePowerState ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PPARAM_DEVICE_POWER_STATE prPowerState; + BOOLEAN fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(REQ, INFO, ("Set Power State: D0\n")); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32)ParamDeviceStateD0); + fgRetValue = nicpmSetAcpiPowerD0(prAdapter); + break; + case ParamDeviceStateD1: + DBGLOG(REQ, INFO, ("Set Power State: D1\n")); + /* no break here */ + case ParamDeviceStateD2: + DBGLOG(REQ, INFO, ("Set Power State: D2\n")); + /* no break here */ + case ParamDeviceStateD3: + DBGLOG(REQ, INFO, ("Set Power State: D3\n")); + fgRetValue = nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32)ParamDeviceStateD3); + break; + default: + break; + } + + if(fgRetValue == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} /* end of wlanoidSetAcpiDevicePowerState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current fragmentation threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFragThreshold ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryFragThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + DBGLOG(REQ, LOUD, ("\n")); + +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidQueryFragThreshold() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new fragmentation threshold to the +* driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFragThreshold ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidSetFragThreshold() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RTS threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRtsThreshold ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + DBGLOG(REQ, LOUD, ("\n")); + + if (u4QueryBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + *pu4QueryInfoLen = sizeof(PARAM_RTS_THRESHOLD); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((PARAM_RTS_THRESHOLD *)pvQueryBuffer) = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryRtsThreshold */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new RTS threshold to the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRtsThreshold ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PARAM_RTS_THRESHOLD *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RTS_THRESHOLD); + if (u4SetBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (PARAM_RTS_THRESHOLD *)pvSetBuffer; + *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to turn radio off. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDisassociate ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set disassociate! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen!=0) { + ASSERT(pvQueryBuffer); + +// *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); + *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_AIS_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + + // hack for CTIA power mode setting function + if (prAdapter->fgEnCtiaPowerMode) { + // set to non-zero value (to prevent MMI query 0, before it intends to set 0, which will skip its following state machine) + *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)2; + } + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSet802dot11PowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + //WARNLOG(("Invalid power mode %d\n", + //*(PPARAM_POWER_MODE) pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + + } else { + // User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) + + if (prAdapter->u4CtiaPowerMode == 0) { + // force to keep in CAM mode + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + status = nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_AIS_INDEX, + ePowerMode, + TRUE); + + switch (ePowerMode) { + case Param_PowerModeCAM: + DBGLOG(INIT, INFO, ("Set Wi-Fi PS mode to CAM (%d)\n", ePowerMode)); + break; + case Param_PowerModeMAX_PSP: + DBGLOG(INIT, INFO, ("Set Wi-Fi PS mode to MAX PS (%d)\n", ePowerMode)); + break; + case Param_PowerModeFast_PSP: + DBGLOG(INIT, INFO, ("Set Wi-Fi PS mode to FAST PS (%d)\n", ePowerMode)); + break; + default: + DBGLOG(INIT, INFO, ("invalid Wi-Fi PS mode setting (%d)\n", ePowerMode)); + break; + } + + return status; + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current status of AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAdHocMode ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryAdHocMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAdHocMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAdHocMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query RF frequency. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFrequency ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + *(PUINT_32)pvQueryBuffer = + nicChannelNum2Freq(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].ucPrimaryChannel); + } + else { + *(PUINT_32)pvQueryBuffer = 0; + } + } + else { + *(PUINT_32)pvQueryBuffer = + nicChannelNum2Freq(prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum); + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryFrequency() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set RF frequency by User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFrequency ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_32 pu4FreqInKHz; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (PUINT_32)pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum + = (UINT_8)nicFreq2ChannelNum(*pu4FreqInKHz); + prAdapter->rWifiVar.rConnSettings.eAdHocBand + = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetFrequency() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set 802.11 channel of the radio frequency. +* This is a proprietary function call to Lunux currently. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChannel ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + ASSERT(0); //// + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the Beacon Interval from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBeaconInterval ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + *(PUINT_32)pvQueryBuffer = + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod; + } + else { + *(PUINT_32)pvQueryBuffer = + (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } + } + else { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + *(PUINT_32)pvQueryBuffer = 0; + } + else { + *(PUINT_32)pvQueryBuffer = + (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryBeaconInterval() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the Beacon Interval to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBeaconInterval ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_32 pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (PUINT_32)pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) || + (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(REQ, TRACE, ("Invalid Beacon Interval = %ld\n", *pu4BeaconInterval)); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16)*pu4BeaconInterval; + + DBGLOG(REQ, INFO, ("Set beacon interval: %d\n", + prAdapter->rWlanInfo.u2BeaconPeriod)); + + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBeaconInterval() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the ATIM window from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAtimWindow ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + *(PUINT_32)pvQueryBuffer = 0; + } + else { + *(PUINT_32)pvQueryBuffer = + (UINT_32) prAdapter->rWlanInfo.u2AtimWindow; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryAtimWindow() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the ATIM window to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAtimWindow ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_32 pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + pu4AtimWindow = (PUINT_32)pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (UINT_16)*pu4AtimWindow; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the MAC address which is currently used by the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + ASSERT(0); //// + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetCurrentAddr() */ + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the checksum offload function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCSUMOffload ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + UINT_32 i, u4CSUMFlags; + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(PUINT_32)pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + for(i = 0 ; i < 6 ; i++) { // set to broadcast address for not-specified + rCmdBasicConfig.rMyMacAddr[i] = 0xff; + } + + rCmdBasicConfig.ucNative80211 = 0; //@FIXME: for Vista + + if(u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(2); + + if(u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(1); + + if(u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(0); + + if(u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(2); + + if(u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(1); + + if(u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(0); + + prAdapter->u4CSUMFlags = u4CSUMFlags; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), + (PUINT_8)&rCmdBasicConfig, + pvSetBuffer, + u4SetBufferLen + ); +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkAddress( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST)pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8)pvSetBuffer; + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) { + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for ( i = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + // construct payload of command packet + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + if (u4IpAddressCount == 0) { + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + } + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if(prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + // fill P_CMD_SET_NETWORK_ADDRESS_LIST + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8)u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(REQ, INFO, ("u4IpAddressCount (%d)\n", u4IpAddressCount)); + + for (i = 0, j = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP)prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), + sizeof(UINT_32)); + + j++; + + pucBuf = (PUINT_8)&prNetAddrIp->in_addr; + DBGLOG(REQ, INFO, ("prNetAddrIp->in_addr:%d:%d:%d:%d\n", pucBuf[0], pucBuf[1],pucBuf[2],pucBuf[3])); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (PUINT_8)prCmdNetworkAddressList, + pvSetBuffer, + u4SetBufferLen + ); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set, +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetTestMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if(u4SetBufferLen == 0) { + if(prAdapter->fgTestMode == FALSE) { + // switch to RF Test mode + rCmdTestCtrl.ucAction = 0; // Switch mode + rCmdTestCtrl.u.u4OpMode = 1; // RF test mode + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8)&rCmdTestCtrl, + pvSetBuffer, + u4SetBufferLen); + } + else { + // already in test mode .. + rStatus = WLAN_STATUS_SUCCESS; + } + } + else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into normal operation mode from RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAbortTestMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if(u4SetBufferLen == 0) { + if(prAdapter->fgTestMode == TRUE) { + // switch to normal mode + rCmdTestCtrl.ucAction = 0; // Switch mode + rCmdTestCtrl.u.u4OpMode = 0; // normal mode + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventLeaveRfTest, + nicOidCmdTimeoutCommon, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8)&rCmdTestCtrl, + pvSetBuffer, + u4SetBufferLen); + } + else { + // already in normal mode .. + rStatus = WLAN_STATUS_SUCCESS; + } + } + else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + + return rStatus; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief query for RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestQueryAutoTest ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_MTK_WIFI_TEST_STRUC_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUC_T); + + if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUC_T)) { + DBGLOG(REQ, ERROR, ("Invalid data. QueryBufferLen: %ld.\n", + u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUC_T)pvQueryBuffer; + rStatus = rftestQueryATInfo(prAdapter, + prRfATInfo->u4FuncIndex, + prRfATInfo->u4FuncData, + pvQueryBuffer, + u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAutoTest ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_MTK_WIFI_TEST_STRUC_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUC_T); + + if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUC_T)) { + DBGLOG(REQ, ERROR, ("Invalid data. SetBufferLen: %ld.\n", + u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUC_T)pvSetBuffer; + rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +WLAN_STATUS +rftestSetATInfo ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, + UINT_32 u4FuncData + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + // Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T)(prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 1; // Set ATInfo + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS +rftestQueryATInfo( + IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, + UINT_32 u4FuncData, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + P_EVENT_TEST_STATUS prTestStatus; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + if(u4FuncIndex == RF_AT_FUNCID_FW_INFO) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS)pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + else if(u4FuncIndex == RF_AT_FUNCID_DRV_INFO) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS)pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = CFG_DRV_OWN_VERSION; + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + else { + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = pvQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; + + // Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T)(prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 2; // Get ATInfo + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; + } +} + +WLAN_STATUS +rftestSetFrequency( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4FreqInKHz, + IN PUINT_32 pu4SetInfoLen + ) +{ + CMD_TEST_CTRL_T rCmdTestCtrl; + + ASSERT(prAdapter); + + rCmdTestCtrl.ucAction = 5; // Set Channel Frequency + rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8)&rCmdTestCtrl, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, + OUT PVOID pvSetQueryBuffer, + IN UINT_32 u4SetQueryBufferLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, ("ucCmdSeqNum =%d\n", ucCmdSeqNum)); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + // Setup WIFI_CMD_T (no payload) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if(u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) { + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + + + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI ui to set wapi mode, which is needed to info the the driver +* to operation at WAPI mode while driver initialize. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + DEBUGFUNC("wlanoidSetWapiMode"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* Todo:: For support WAPI and Wi-Fi at same driver, use the set wapi assoc ie at the check point */ + /* The Adapter Connection setting fgUseWapi will cleat whil oid set mode (infra), */ + /* And set fgUseWapi True while set wapi assoc ie */ + /* policay selection, add key all depend on this flag, */ + /* The fgUseWapi may remove later */ + if (*(PUINT_32)pvSetBuffer) { + prAdapter->fgUseWapi = TRUE; + } + else { + prAdapter->fgUseWapi = FALSE; + } + +#if 0 + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + 4)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_BUILD_CONNECTION cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + 4; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_WAPI_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + cp = (PUINT_8)(prWifiCmd->aucBuffer); + + kalMemCopy(cp, (PUINT_8)pvSetBuffer, 4); + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +#else + return WLAN_STATUS_SUCCESS; +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI to set the assoc info, which is needed to add to +* Association request frame while join WAPI AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiAssocInfo ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_WAPI_INFO_ELEM_T prWapiInfo; + PUINT_8 cp; + UINT_16 u2AuthSuiteCount = 0; + UINT_16 u2PairSuiteCount = 0; + UINT_32 u4AuthKeyMgtSuite = 0; + UINT_32 u4PairSuite = 0; + UINT_32 u4GroupSuite = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(REQ, LOUD, ("\r\n")); + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) { + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + return WLAN_STATUS_INVALID_LENGTH; + } + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; + + //if (prWapiInfo->ucElemId != ELEM_ID_WAPI) + // DBGLOG(SEC, TRACE, ("Not WAPI IE ?!\n")); + + //if (prWapiInfo->ucLength < 18) + // return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prWapiInfo = (P_WAPI_INFO_ELEM_T)pvSetBuffer; + + if (prWapiInfo->ucElemId != ELEM_ID_WAPI) { + DBGLOG(SEC, TRACE, ("Not WAPI IE ?! u4SetBufferLen = %d\n", u4SetBufferLen)); + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + /* Skip Version check */ + cp = (PUINT_8)&prWapiInfo->u2AuthKeyMgtSuiteCount; + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + + if (u2AuthSuiteCount>1) + return WLAN_STATUS_INVALID_LENGTH; + + cp += 2; + WLAN_GET_FIELD_32(cp, &u4AuthKeyMgtSuite); + + DBGLOG(SEC, TRACE, ("WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", + u2AuthSuiteCount, + (UCHAR) (u4AuthKeyMgtSuite & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 8) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 16) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 24) & 0x000000FF))); + + if (u4AuthKeyMgtSuite != WAPI_AKM_SUITE_802_1X && + u4AuthKeyMgtSuite != WAPI_AKM_SUITE_PSK) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + if (u2PairSuiteCount>1) + return WLAN_STATUS_INVALID_LENGTH; + + cp += 2; + WLAN_GET_FIELD_32(cp, &u4PairSuite); + DBGLOG(SEC, TRACE, ("WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", + u2PairSuiteCount, + (UCHAR) (u4PairSuite & 0x000000FF), + (UCHAR) ((u4PairSuite >> 8) & 0x000000FF), + (UCHAR) ((u4PairSuite >> 16) & 0x000000FF), + (UCHAR) ((u4PairSuite >> 24) & 0x000000FF))); + + if (u4PairSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + DBGLOG(SEC, TRACE, ("WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", + (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF))); + + if (u4GroupSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite = u4AuthKeyMgtSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher = u4PairSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher = u4GroupSuite; + + kalMemCopy(prAdapter->prGlueInfo->aucWapiAssocInfoIEs, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = (UINT_16)u4SetBufferLen; + DBGLOG(SEC, TRACE, ("Assoc Info IE sz %ld\n", u4SetBufferLen)); + + return WLAN_STATUS_SUCCESS; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the wpi key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer P_PARAM_WPI_KEY, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiKey ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_WPI_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + PUINT_8 pc; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetWapiKey"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\r\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_WPI_KEY_T) pvSetBuffer; + + DBGLOG_MEM8(REQ, TRACE, (PUINT_8)pvSetBuffer, 560); + pc = (PUINT_8)pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Exception check */ + if (prNewKey->ucKeyID != 0x1 || + prNewKey->ucKeyID != 0x0) { + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + //DBGLOG(SEC, INFO, ("Invalid WAPI key ID (%d)\r\n", prNewKey->ucKeyID)); + } + + /* Dump P_PARAM_WPI_KEY_T content. */ + DBGLOG(REQ, TRACE, ("Set: Dump P_PARAM_WPI_KEY_T content\r\n")); + DBGLOG(REQ, TRACE, ("TYPE : %d\r\n", prNewKey->eKeyType)); + DBGLOG(REQ, TRACE, ("Direction : %d\r\n", prNewKey->eDirection)); + DBGLOG(REQ, TRACE, ("KeyID : %d\r\n", prNewKey->ucKeyID)); + DBGLOG(REQ, TRACE, ("AddressIndex:\r\n")); + DBGLOG_MEM8(REQ, TRACE, prNewKey->aucAddrIndex, 12); + prNewKey->u4LenWPIEK = 16; + + DBGLOG_MEM8(REQ, TRACE, (PUINT_8)prNewKey->aucWPIEK, (UINT_8)prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(REQ, TRACE, ("CK Key(%d):\r\n", (UINT_8)prNewKey->u4LenWPICK)); + DBGLOG_MEM8(REQ, TRACE, (PUINT_8)prNewKey->aucWPICK, (UINT_8)prNewKey->u4LenWPICK); + DBGLOG(REQ, TRACE, ("PN:\r\n")); + if (prNewKey->eKeyType == 0){ + prNewKey->aucPN[0] = 0x5c; + prNewKey->aucPN[1] = 0x36; + prNewKey->aucPN[2] = 0x5c; + prNewKey->aucPN[3] = 0x36; + prNewKey->aucPN[4] = 0x5c; + prNewKey->aucPN[5] = 0x36; + prNewKey->aucPN[6] = 0x5c; + prNewKey->aucPN[7] = 0x36; + prNewKey->aucPN[8] = 0x5c; + prNewKey->aucPN[9] = 0x36; + prNewKey->aucPN[10] = 0x5c; + prNewKey->aucPN[11] = 0x36; + prNewKey->aucPN[12] = 0x5c; + prNewKey->aucPN[13] = 0x36; + prNewKey->aucPN[14] = 0x5c; + prNewKey->aucPN[15] = 0x36; + } + + DBGLOG_MEM8(REQ, TRACE, (PUINT_8)prNewKey->aucPN, 16); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + // compose CMD_ID_ADD_REMOVE_KEY cmd pkt + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + // Setup WIFI_CMD_T + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY)(prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { + prCmdKey->ucTxKey = 1; + prCmdKey->ucKeyType = 1; + } + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8)prNewKey->aucAddrIndex, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = prNewKey->ucKeyID; + + prCmdKey->ucKeyLen = 32; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8)prNewKey->aucWPIEK, 16); + + kalMemCopy(prCmdKey->aucKeyMaterial+16, (PUINT_8)prNewKey->aucWPICK, 16); + + kalMemCopy(prCmdKey->aucKeyRsc, (PUINT_8)prNewKey->aucPN, 16); + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddKey */ +#endif + + +#if CFG_SUPPORT_WPS2 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the assoc info, which is needed to add to +* Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWSCAssocInfo ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWSCAssocInfo"); + DBGLOG(REQ, LOUD, ("\r\n")); + + if(u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + kalMemCopy(prAdapter->prGlueInfo->aucWSCAssocInfoIE, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2WSCAssocInfoIELen = (UINT_16)u4SetBufferLen; + DBGLOG(SEC, TRACE, ("Assoc Info IE sz %ld\n", u4SetBufferLen)); + + return WLAN_STATUS_SUCCESS; + +} +#endif + + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* FIXME: + * Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* FIXME: + * Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + + +WLAN_STATUS +wlanoidQueryEnableWakeup ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + pu4WakeupEventEnable = (PUINT_32)pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetEnableWakeup ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (PUINT_32)pvSetBuffer; + prAdapter->u4WakeupEventEnable = *pu4WakeupEventEnable; + + /* FIXME: + * Send Command Event for setting wakeup-pattern / Magic Packet to firmware + * */ + + return WLAN_STATUS_FAILURE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure PS related settings for WMM-PS test. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWiFiWmmPsTest ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_WMM_PS_TEST_STRUC_T prWmmPsTestInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_SET_WMM_PS_TEST_STRUC_T rSetWmmPsTestParam; + UINT_16 u2CmdBufLen; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUC_T); + + prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUC_T) pvSetBuffer; + + rSetWmmPsTestParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[rSetWmmPsTestParam.ucNetTypeIndex]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUC_T); + +#if 0 + /* it will apply the disable trig or not immediately */ + if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) { +// NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); + } + else { +// NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); + } +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_WMM_PS_TEST_PARMS, + TRUE, + FALSE, + TRUE, + NULL, // TODO? + NULL, + u2CmdBufLen, + (PUINT_8)&rSetWmmPsTestParam, + NULL, + 0); + + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure enable/disable TX A-MPDU feature. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxAmpdu ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_TX_AMPDU_T rTxAmpdu; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + u2CmdBufLen, + (PUINT_8)&rTxAmpdu, + NULL, + 0); + + + return rStatus; +} /* wlanoidSetTxAmpdu */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure reject/accept ADDBA Request. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddbaReject( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_ADDBA_REJECT_T rAddbaReject; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADDBA_REJECT, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + u2CmdBufLen, + (PUINT_8)&rAddbaReject, + NULL, + 0); + + + return rStatus; +} /* wlanoidSetAddbaReject */ + + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUC_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T)NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T)NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUC_T); + + if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T)pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: + { + P_PARAM_MTK_SLT_LP_TEST_STRUC_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUC_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)&prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + // TBD... + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +WLAN_STATUS +wlanoidUpdateSLTMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUC_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T)NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T)NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T)NULL; + + /* 1. Action: Update or Initial Set + * 2. Role. + * 3. Target MAC address. + * 4. RF BW & Rate Settings + */ + + DEBUGFUNC("wlanoidUpdateSLTMode"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T) pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ + { + P_PARAM_MTK_SLT_INITIAL_STRUC_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUC_T)NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUC_T)); + + prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUC_T)&prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, + BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + } while (FALSE); + } + else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + } + else { + P_PARAM_MTK_SLT_TR_TEST_STRUC_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUC_T)NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUC_T)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUC_T)&prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; /* It would controls RFBW capability in WTBL. */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; /* This controls RF BW, RF BW would be 40 only if + * 1. PHY_TYPE_BIT_HT is TRUE. + * 2. SCO is SCA/SCB. + */ + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = CHNL_EXT_SCB; // +2 + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel += 2; + } + else { + if (prBssInfo->ucPrimaryChannel <5) { + prBssInfo->ucPrimaryChannel = 8; // For channel 1, testing L20 at channel 8. + } + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = CHNL_EXT_SCA; // -2 + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel -= 2; + } + else { + if (prBssInfo->ucPrimaryChannel > 10) { + prBssInfo->ucPrimaryChannel = 3; // For channel 11 / 14. testing U20 at channel 3. + } + } + break; + } + } + else { + /* RF 20 */ + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + + prStaRec->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + switch (prTRSetting->u4FixedRate & 0xFF) { + case RATE_OFDM_54M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_54M_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; +#if 0 // Only for Current Measurement Mode. + prStaRec->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); +#endif + break; + case RATE_GF_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + } + break; + case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ + { + P_PARAM_MTK_SLT_LP_TEST_STRUC_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUC_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)&prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + + + + return WLAN_STATUS_FAILURE; + + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query NVRAM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNvramRead ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + UINT_16 u2Data; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T)pvQueryBuffer; + + if(prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, /* change to byte offset */ + &u2Data); + + if(fgStatus) { + prNvramRwInfo->u2EepromData = u2Data; + DBGLOG(REQ, INFO, ("NVRAM Read: index=%#X, data=%#02X\r\n", + prNvramRwInfo->ucEepromIndex, u2Data)); + } + else{ + DBGLOG(REQ, ERROR, ("NVRAM Read Failed: index=%#x.\r\n", + prNvramRwInfo->ucEepromIndex)); + rStatus = WLAN_STATUS_FAILURE; + } + } + else if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_GETSIZE) { + prNvramRwInfo->u2EepromData = CFG_FILE_WIFI_REC_SIZE; + DBGLOG(REQ, INFO, ("EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData)); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T); + + return rStatus; +} /* wlanoidQueryNvramRead */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write NVRAM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNvramWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T)pvSetBuffer; + + fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, /* change to byte offset */ + prNvramRwInfo->u2EepromData + ); + + if(fgStatus == FALSE){ + DBGLOG(REQ, ERROR, ("NVRAM Write Failed.\r\n")); + rStatus = WLAN_STATUS_FAILURE; + } + + return rStatus; +} /* wlanoidSetNvramWrite */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCfgSrcType( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(ENUM_CFG_SRC_TYPE_T); + + if(kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + *(P_ENUM_CFG_SRC_TYPE_T)pvQueryBuffer = CFG_SRC_TYPE_NVRAM; + } + else { + *(P_ENUM_CFG_SRC_TYPE_T)pvQueryBuffer = CFG_SRC_TYPE_EEPROM; + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromType( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(P_ENUM_EEPROM_TYPE_T); + +#if CFG_SUPPORT_NIC_CAPABILITY + if(prAdapter->fgIsEepromUsed == TRUE) { + *( P_ENUM_EEPROM_TYPE_T )pvQueryBuffer = EEPROM_TYPE_PRESENT; + } + else { + *( P_ENUM_EEPROM_TYPE_T )pvQueryBuffer = EEPROM_TYPE_NO; + } +#else + *( P_ENUM_EEPROM_TYPE_T )pvQueryBuffer = EEPROM_TYPE_NO; +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCountryCode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_8 pucCountry; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]) ; + + prAdapter->prDomainInfo = NULL; /* Force to re-search country code */ + rlmDomainSendCmd(prAdapter, TRUE); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUC_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUC_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_T), + (PUINT_8)&rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen + ); +} + +WLAN_STATUS +wlanoidSetOppPsParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUC_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen + ); +} + +WLAN_STATUS +wlanoidSetUApsdParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUC_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | + (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | + (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen + ); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set BT profile or BT information and the +* driver will set the built-in PTA configuration into chip. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + + P_PTA_IPC_T prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PTA_IPC_T); + if (u4SetBufferLen != sizeof(PTA_IPC_T)) { + WARNLOG(("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail to set BT profile because of ACPI_D3\n")); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prPtaIpc = (P_PTA_IPC_T)pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + printk(KERN_INFO DRV_NAME "BCM BWCS CMD: BWCS CMD = %02x%02x%02x%02x\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], prPtaIpc->u.aucBTPParams[3]); + + printk(KERN_INFO DRV_NAME "BCM BWCS CMD: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], + prPtaIpc->u.aucBTPParams[1], + prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]); +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BWCS, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(PTA_IPC_T), + (PUINT_8)prPtaIpc, + NULL, + 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current BT profile and BTCR values +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBT ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ +// P_PARAM_PTA_IPC_T prPtaIpc; +// UINT_32 u4QueryBuffLen; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PTA_IPC_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(PTA_IPC_T)) { + DBGLOG(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); +// prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; +// prPtaIpc->ucCmd = BT_CMD_PROFILE; +// prPtaIpc->ucLen = sizeof(prPtaIpc->u); +// nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidQueryBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (PUINT_32)pvQueryBuffer; + + if(prPtaInfo->fgSingleAntenna) { + //printk(KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n"); + *pu4SingleAntenna = 1; + } else { + //printk(KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n"); + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + + +WLAN_STATUS +wlanoidSetBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + + PUINT_32 pu4SingleAntenna; + UINT_32 u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { + return WLAN_STATUS_SUCCESS; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail to set antenna because of ACPI_D3\n")); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4SingleAntenna = (PUINT_32)pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + //printk(KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n"); + prPtaInfo->fgSingleAntenna = FALSE; + } else { + //printk(KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n"); + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +WLAN_STATUS +wlanoidQueryPta ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (PUINT_32)pvQueryBuffer; + + if(prPtaInfo->fgEnabled) { + //printk(KERN_WARNING DRV_NAME"PTA = 1\r\n"); + *pu4Pta = 1; + } else { + //printk(KERN_WARNING DRV_NAME"PTA = 0\r\n"); + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + + +WLAN_STATUS +wlanoidSetPta ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + PUINT_32 pu4PtaCtrl; + UINT_32 u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { + return WLAN_STATUS_SUCCESS; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail to set BT setting because of ACPI_D3\n")); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4PtaCtrl = (PUINT_32)pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + //printk(KERN_WARNING DRV_NAME"Set Pta= 0\r\n"); + nicPtaSetFunc(prAdapter, FALSE); + } else { + //printk(KERN_WARNING DRV_NAME"Set Pta= 1\r\n"); + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Tx power profile. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxPower ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + //P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T)pvSetBuffer; + //UINT_32 i; + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(REQ, LOUD, ("\r\n")); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + printk("c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); + printk("c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); + printk("c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); + printk("c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); + printk("c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); + printk("c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); + printk("c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); + printk("c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); + printk("ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); + + for (i=0; i<14;i++) + printk("acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); + + for (i=0; i<4;i++) + printk("acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return rStatus; + +} + +WLAN_STATUS +wlanSendMemDumpCmd ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen + ) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUC_T prMemDumpInfo; + P_CMD_DUMP_MEM prCmdDumpMem; + CMD_DUMP_MEM rCmdDumpMem; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + UINT_32 u4RemainLeng = 0; + UINT_32 u4CurAddr = 0; + UINT_8 ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUC_T)pvQueryBuffer; + + u4RemainLeng = prMemDumpInfo->u4RemainLength; + u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; + ucFragNum = prMemDumpInfo->ucFragNum + 1; + + /* Query. If request length is larger than max length, do it as ping pong. + * Send a command and wait for a event. Send next command while the event is received. + * + */ + do{ + UINT_32 u4CurLeng = 0; + + if(u4RemainLeng > u4MemSize) { + u4CurLeng = u4MemSize; + u4RemainLeng -= u4MemSize; + } else { + u4CurLeng = u4RemainLeng; + u4RemainLeng = 0; + } + + prCmdDumpMem->u4Address = u4CurAddr; + prCmdDumpMem->u4Length = u4CurLeng; + prCmdDumpMem->u4RemainLength = u4RemainLeng; + prCmdDumpMem->ucFragNum = ucFragNum; + + DBGLOG(REQ, TRACE, ("[%d] 0x%X, len %d, remain len %d\n", + ucFragNum, + prCmdDumpMem->u4Address, + prCmdDumpMem->u4Length, + prCmdDumpMem->u4RemainLength)); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(CMD_DUMP_MEM), + (PUINT_8)prCmdDumpMem, + pvQueryBuffer, + u4QueryBufferLen + ); + + }while(FALSE); + + return rStatus; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump memory. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMemDump ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUC_T prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(INIT, LOUD,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(UINT_32); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUC_T)pvQueryBuffer; + DBGLOG(REQ, TRACE, ("Dump 0x%X, len %d\n", prMemDumpInfo->u4Address, prMemDumpInfo->u4Length)); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd( + prAdapter, + pvQueryBuffer, + u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the p2p mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS status; + P_PARAM_CUSTOM_P2P_SET_STRUC_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUC_T)NULL; + //P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T); + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUC_T) pvSetBuffer; + + DBGLOG(P2P, INFO, ("Set P2P enable[%ld] mode[%ld]\n", prSetP2P->u4Enable, prSetP2P->u4Mode)); + + /* + * enable = 1, mode = 0 => init P2P network + * enable = 1, mode = 1 => init Soft AP network + * enable = 0 => uninit P2P/AP network + */ + + if (prSetP2P->u4Enable) { + p2pSetMode((prSetP2P->u4Mode == 1)?TRUE:FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) { + ASSERT(prAdapter->fgIsP2PRegistered); + } + + } + else { + if (prAdapter->fgIsP2PRegistered) { + p2pRemove(prAdapter->prGlueInfo); + } + + } + + +#if 0 + prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_NETDEV_REGISTER_T))); + + if (prP2pNetdevRegMsg == NULL) { + ASSERT(FALSE); + status = WLAN_STATUS_RESOURCES; + return status; + } + + + prP2pNetdevRegMsg->rMsgHdr.eMsgId = MID_MNY_P2P_NET_DEV_REGISTER; + prP2pNetdevRegMsg->fgIsEnable = (prSetP2P->u4Enable == 1)?TRUE:FALSE; + prP2pNetdevRegMsg->ucMode = (UINT_8)prSetP2P->u4Mode; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pNetdevRegMsg, + MSG_SEND_METHOD_BUF); +#endif + + return status; + +} +#endif + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c new file mode 100755 index 000000000000..be51207a7f16 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c @@ -0,0 +1,1811 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/common/wlan_p2p.c#8 $ +*/ + +/*! \file wlan_bow.c + \brief This file contains the Wi-Fi Direct commands processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_p2p.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 24 2011 yuche.tsai + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channle Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 23 2011 yuche.tsai + * NULL + * Fix Multicast Issue of P2P. + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 wh.su + * [WCXRP00000571] [MT6620 Wi-Fi] [Driver] Not check the p2p role during set key + * Skip the p2p role for adding broadcast key issue. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * fixed compiling error while enable dbg. + * + * 03 08 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue[WCXRP00000509] [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix SD Request Query Length issue. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Service Discovery Request. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Wlan OID related function. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * . + * + * 08 16 2010 george.huang + * NULL + * support wlanoidSetP2pPowerSaveProfile() in P2P + * + * 08 16 2010 george.huang + * NULL + * Support wlanoidSetNetworkAddress() for P2P + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, + OUT PVOID pvSetQueryBuffer, + IN UINT_32 u4SetQueryBufferLen + ) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DEBUGFUNC("wlanoidSendSetQueryP2PCmd"); + DBGLOG(REQ, TRACE, ("Command ID = 0x%08X\n", ucCID)); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, ("ucCmdSeqNum =%d\n", ucCmdSeqNum)); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_P2P_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + // Setup WIFI_CMD_T (no payload) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if(u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) { + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to Wi-Fi Direct driver +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddP2PKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + CMD_802_11_KEY rCmdKey; + P_PARAM_KEY_T prNewKey; + + DEBUGFUNC("wlanoidSetAddP2PKey"); + DBGLOG(REQ, INFO, ("\n")); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(REQ, WARN, ("Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8)prNewKey->u4Length, + (UINT_8)u4SetBufferLen)); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + /* Verify the key material length for key material buffer */ + else if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(REQ, WARN, ("Invalid key material length (%d)\n", (UINT_8)prNewKey->u4KeyLength)); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + /* Exception check */ + else if (prNewKey->u4KeyIndex & 0x0fffff00) { + return WLAN_STATUS_INVALID_DATA; + } + /* Exception check, pairwise key must with transmit bit enabled */ + else if ((prNewKey->u4KeyIndex & BITS(30,31)) == IS_UNICAST_KEY) { + return WLAN_STATUS_INVALID_DATA; + } + else if (!(prNewKey->u4KeyLength == CCMP_KEY_LEN) && !(prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + /* Exception check, pairwise key must with transmit bit enabled */ + else if ((prNewKey->u4KeyIndex & BITS(30,31)) == BITS(30,31)) { + if (((prNewKey->u4KeyIndex & 0xff) != 0) || + ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) && + (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) && (prNewKey->arBSSID[5] == 0xff))) { + return WLAN_STATUS_INVALID_DATA; + } + } + + *pu4SetInfoLen = u4SetBufferLen; + + // fill CMD_802_11_KEY + kalMemZero(&rCmdKey, sizeof(CMD_802_11_KEY)); + rCmdKey.ucAddRemove = 1; /* add */ + rCmdKey.ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; + rCmdKey.ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + if(kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } + else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; + if(prNewKey->u4KeyLength == CCMP_KEY_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; // AES + else if(prNewKey->u4KeyLength == TKIP_KEY_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_TKIP; // TKIP + rCmdKey.ucKeyId = (UINT_8)(prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (UINT_8)prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8)prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), + (PUINT_8)&rCmdKey, + pvSetBuffer, + u4SetBufferLen + ); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request Wi-Fi Direct driver to remove keys +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveP2PKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + CMD_802_11_KEY rCmdKey; + P_PARAM_REMOVE_KEY_T prRemovedKey; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T)pvSetBuffer; + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, ("invalid key index: 0x%08lx\n", + prRemovedKey->u4KeyIndex)); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, ("invalid key index: 0x%08lx\n", + prRemovedKey->u4KeyIndex)); + return WLAN_STATUS_INVALID_DATA; + } + + /* There should not be any key operation for P2P Device */ + if(kalP2PGetRole(prAdapter->prGlueInfo) == 0) { + // return WLAN_STATUS_NOT_ACCEPTED; + } + + kalMemZero((PUINT_8)&rCmdKey, sizeof(CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; // remove + if(kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } + else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8)prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; + rCmdKey.ucKeyId = (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), + (PUINT_8)&rCmdKey, + pvSetBuffer, + u4SetBufferLen + ); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pNetworkAddress( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST)pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + + DEBUGFUNC("wlanoidSetP2pNetworkAddress"); + DBGLOG(INIT, TRACE, ("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) { + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for ( i = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + // construct payload of command packet + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if(prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + // fill P_CMD_SET_NETWORK_ADDRESS_LIST + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prCmdNetworkAddressList->ucAddressCount = (UINT_8)u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0, j = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP)prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), + sizeof(UINT_32)); + + j++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (PUINT_8)prCmdNetworkAddressList, + pvSetBuffer, + u4SetBufferLen + ); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen!=0) { + ASSERT(pvQueryBuffer); + + *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + WARNLOG(("Invalid power mode %d\n", + *(PPARAM_POWER_MODE) pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + + } else { + // User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) + + if (prAdapter->u4CtiaPowerMode == 0) { + // force to keep in CAM mode + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + status = nicConfigPowerSaveProfile( + prAdapter, + NETWORK_TYPE_P2P_INDEX, + ePowerMode, + TRUE); + return status; +} /* end of wlanoidSetP2pPowerSaveProfile() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST)pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8)pvSetBuffer; + + DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); + DBGLOG(INIT, TRACE, ("\n")); + printk("wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16)u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) { + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for ( i = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + // construct payload of command packet + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) { + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + } + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if(prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + // fill P_CMD_SET_NETWORK_ADDRESS_LIST + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8)u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + printk("u4IpAddressCount (%ld) \n", (INT_32)u4IpAddressCount); + for (i = 0, j = 0 ; i < prNetworkAddressList->u4AddressCount ; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP)prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), + sizeof(UINT_32)); + + j++; + + pucBuf = (PUINT_8)&prNetAddrIp->in_addr; + printk("prNetAddrIp->in_addr:%d:%d:%d:%d\n", (UINT_8)pucBuf[0], (UINT_8)pucBuf[1], (UINT_8)pucBuf[2], (UINT_8)pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress + + (UINT_32) (prNetworkAddress->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (PUINT_8)prCmdNetworkAddressList, + pvSetBuffer, + u4SetBufferLen + ); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} /* end of wlanoidSetP2pSetNetworkAddress() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PMulticastList( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, ("Invalid MC list length %ld\n", u4SetBufferLen)); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / + MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { + DBGLOG(REQ, WARN, ("Too many MC addresses\n")); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) { + ASSERT(pvSetBuffer); + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + FALSE, // This CMD response is no need to complete the OID. Or the event would unsync. + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8)&rCmdMacMcastAddr, + pvSetBuffer, + u4SetBufferLen + ); + +} /* end of wlanoidSetP2PMulticastList() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) { + ASSERT(pvSetBuffer); + } + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + +// rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); + + return rWlanStatus; +} /* end of wlanoidSendP2PSDRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) { + ASSERT(pvSetBuffer); + } + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + +// rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + PUINT_8 pucPacketBuffer = NULL, pucTA = NULL; +// PUINT_8 pucChannelNum = NULL; + PUINT_16 pu2PacketLength = NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; + UINT_8 ucVersionNum = 0; +// UINT_8 ucChannelNum = 0, ucSeqNum = 0; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, ("Get Service Discovery Request\n")); +#if 0 + if ((ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter)) == 0) { + P_PARAM_P2P_GET_SD_REQUEST prP2pGetSdReq = (P_PARAM_P2P_GET_SD_REQUEST)pvQueryBuffer; + + pucPacketBuffer = prP2pGetSdReq->aucPacketContent; + pu2PacketLength = &prP2pGetSdReq->u2PacketLength; + pucTA = &prP2pGetSdReq->rTransmitterAddr; + } + else { + P_PARAM_P2P_GET_SD_REQUEST_EX prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST_EX)NULL; + + prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST)pvQueryBuffer; + pucPacketBuffer = prP2pGetSdReqEx->aucPacketContent; + pu2PacketLength = &prP2pGetSdReqEx->u2PacketLength; + pucTA = &prP2pGetSdReqEx->rTransmitterAddr; + pucChannelNum = &prP2pGetSdReqEx->ucChannelNum; + ucSeqNum = prP2pGetSdReqEx->ucSeqNum; + } + + + rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, + pucPacketBuffer, + (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_REQUEST)), + (PUINT_32)pu2PacketLength, + pucChannelNum, + ucSeqNum); +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + + prWlanHdr = (P_WLAN_MAC_HEADER_T)pucPacketBuffer; + + kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + + if (pu4QueryInfoLen) { + if (ucVersionNum == 0) { + *pu4QueryInfoLen = (UINT_32)(sizeof(PARAM_P2P_GET_SD_REQUEST) + (*pu2PacketLength)); + } + else { + *pu4QueryInfoLen = (UINT_32)(sizeof(PARAM_P2P_GET_SD_REQUEST_EX) + (*pu2PacketLength)); + } + + } + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; + //UINT_8 ucSeqNum = 0, + UINT_8 ucVersionNum = 0; + PUINT_8 pucPacketContent = (PUINT_8)NULL, pucTA = (PUINT_8)NULL; + PUINT_16 pu2PacketLength = (PUINT_16)NULL; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, ("Get Service Discovery Response\n")); + +#if 0 + if ((ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter)) == 0) { + P_PARAM_P2P_GET_SD_RESPONSE prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_RESPONSE)NULL; + + prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_REQUEST)pvQueryBuffer; + pucPacketContent = prP2pGetSdRsp->aucPacketContent; + pucTA = &prP2pGetSdRsp->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRsp->u2PacketLength; + } + else { + P_PARAM_P2P_GET_SD_RESPONSE_EX prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX)NULL; + + prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX)pvQueryBuffer; + pucPacketContent = prP2pGetSdRspEx->aucPacketContent; + pucTA = &prP2pGetSdRspEx->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRspEx->u2PacketLength; + ucSeqNum = prP2pGetSdRspEx->ucSeqNum; + } + + +// rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, +// pucPacketContent, +// (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_RESPONSE)), +// (PUINT_32)pu2PacketLength, +// NULL, +// ucSeqNum); +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + prWlanHdr = (P_WLAN_MAC_HEADER_T)pucPacketContent; + + kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + + + if (pu4QueryInfoLen) { + if (ucVersionNum == 0) { + *pu4QueryInfoLen = (UINT_32)(sizeof(PARAM_P2P_GET_SD_RESPONSE) + *pu2PacketLength); + } + else { + *pu4QueryInfoLen = (UINT_32)(sizeof(PARAM_P2P_GET_SD_RESPONSE_EX) + *pu2PacketLength); + } + } + + return rWlanStatus; +} /* end of wlanoidGetP2PSDResponse() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to terminate P2P Service Discovery Phase +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_P2P_TERMINATE_SD_PHASE prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE)NULL; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) { + break; + } + + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) { + break; + } + + if (u4SetBufferLen < sizeof(PARAM_P2P_TERMINATE_SD_PHASE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_TERMINATE_SD_PHASE); + rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE)pvSetBuffer; + + if (EQUAL_MAC_ADDR(prP2pTerminateSD->rPeerAddr, aucNullAddr)) { + DBGLOG(P2P, TRACE, ("Service Discovery Version 2.0\n")); +// p2pFuncSetVersionNumOfSD(prAdapter, 2); + } + + //rWlanStatus = p2pFsmRunEventSDAbort(prAdapter); + + } while (FALSE); + + + + + + return rWlanStatus; +} /* end of wlanoidSetP2PTerminateSDPhase() */ + + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSecCheckRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) { + ASSERT(pvSetBuffer); + } + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, + (PUINT_8)pvSetBuffer, + pvSetBuffer, + u4SetBufferLen + ); + +} /* end of wlanoidSetSecCheckRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetSecCheckResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + //P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = prAdapter->prGlueInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + if (u4QueryBufferLen > 256) { + u4QueryBufferLen = 256; + } + + *pu4QueryInfoLen = u4QueryBufferLen; + + #if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); + #endif + kalMemCopy((PUINT_8)(pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif + +WLAN_STATUS +wlanoidSetNoaParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUC_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUC_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, TRACE,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_T), + (PUINT_8)&rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen + ); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_T), + (PUINT_8)&rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen + ); + +#endif + +} + +WLAN_STATUS +wlanoidSetOppPsParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUC_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, TRACE,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen + ); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen + ); + +#endif + +} + +WLAN_STATUS +wlanoidSetUApsdParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUC_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, TRACE,("\n")); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T)pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | + (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | + (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen + ); + #else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T), + (PUINT_8)&rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen + ); + +#endif +} + + + +WLAN_STATUS +wlanoidQueryP2pOpChannel ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +// PUINT_8 pucOpChnl = (PUINT_8)pvQueryBuffer; + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) { + break; + } + + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) { + break; + } + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + +#if 0 + if (!p2pFuncGetCurrentOpChnl(prAdapter, pucOpChnl)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } +#else + rResult = WLAN_STATUS_INVALID_DATA; + break; +#endif + + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_SUCCESS; + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pOpChannel */ + +WLAN_STATUS +wlanoidQueryP2pVersion ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +// PUINT_8 pucVersionNum = (PUINT_8)pvQueryBuffer; + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) { + break; + } + + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) { + break; + } + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + UINT_8 ucVersionNum; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) { + + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + *pu4SetInfoLen = sizeof(UINT_8); + + if (u4SetBufferLen < sizeof(UINT_8)) { + rResult = WLAN_STATUS_INVALID_LENGTH; + break; + } + + + ucVersionNum = *((PUINT_8)pvSetBuffer); + + + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidSetP2pSupplicantVersion */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + DEBUGFUNC("wlanoidQueryP2pRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + } + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, ("Too short length %ld\n", u4QueryBufferLen)); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (prAdapter->fgIsP2pLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI)prAdapter->rP2pLinkQuality.cRssi; // ranged from (-128 ~ 30) in unit of dBm + + if(rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if(rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } + + #ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, + pvQueryBuffer, + pvQueryBuffer, + u4QueryBufferLen + ); + #else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + 0, + NULL, + pvQueryBuffer, + u4QueryBufferLen + ); + + #endif +} /* wlanoidQueryP2pRssi */ +#endif + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h new file mode 100755 index 000000000000..dd1fce8d7bf5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h @@ -0,0 +1,251 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/CFG_Wifi_File.h#1 $ +*/ + +/*! \file CFG_Wifi_File.h + \brief Collection of NVRAM structure used for YuSu project + + In this file we collect all compiler flags and detail the driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + + + +/* +** $Log: CFG_Wifi_File.h $ + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 09 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC[WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * update NVRAM data structure definition. + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition + * follow-up for CMD_5G_PWR_OFFSET_T definition change + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * +*/ + +#ifndef _CFG_WIFI_FILE_H +#define _CFG_WIFI_FILE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +// duplicated from nic_cmd_event.h to avoid header dependency +typedef struct _TX_PWR_PARAM_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ +#if defined(MT6620) + INT_8 acReserved[3]; +#elif defined(MT5931) || defined(MT6628) + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; +#else + #error "No valid definition!" +#endif + + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} TX_PWR_PARAM_T, *P_TX_PWR_PARAM_T; + +typedef struct _PWR_5G_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} PWR_5G_OFFSET_T, *P_PWR_5G_OFFSET_T; + +typedef struct _PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} PWR_PARAM_T, *P_PWR_PARAM_T; + +typedef struct _MT6620_CFG_PARAM_STRUCT { + /* 256 bytes of MP data */ + UINT_16 u2Part1OwnVersion; + UINT_16 u2Part1PeerVersion; + UINT_8 aucMacAddress[6]; + UINT_8 aucCountryCode[2]; + TX_PWR_PARAM_T rTxPwr; + UINT_8 aucEFUSE[144]; + UINT_8 ucTxPwrValid; + UINT_8 ucSupport5GBand; + UINT_8 fg2G4BandEdgePwrUsed; + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + + UINT_8 ucRegChannelListMap; + UINT_8 ucRegChannelListIndex; + UINT_8 aucRegSubbandInfo[36]; + + UINT_8 aucReserved2[256-240]; + + /* 256 bytes of function data */ + UINT_16 u2Part2OwnVersion; + UINT_16 u2Part2PeerVersion; + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 aucPreTailReserved; + UINT_8 aucTailReserved[256-8]; +} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, + WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef DATA_STRUC_INSPECTING_ASSERT +#define DATA_STRUC_INSPECTING_ASSERT(expr) \ + switch (0) {case 0: case (expr): default:;} +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +__KAL_INLINE__ VOID +nvramOffsetCheck ( + VOID + ) +{ + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + + DATA_STRUC_INSPECTING_ASSERT( + sizeof(WIFI_CFG_PARAM_STRUCT) == 512); + + DATA_STRUC_INSPECTING_ASSERT( + (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); + + DATA_STRUC_INSPECTING_ASSERT( + (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) == 0); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h new file mode 100755 index 000000000000..d2943bf40f2a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h @@ -0,0 +1,1525 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#2 $ +*/ + +/*! \file "config.h" + \brief This file includes the various configurable parameters for customers + + This file ncludes the configurable parameters except the paramters indicate the turning-on/off of some features +*/ + + + +/* +** $Log: config.h $ + * + * 07 13 2012 cp.wu + * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for termination after SDIO error has happened + * [driver domain] add force reset by host-to-device interrupt mechanism + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 06 05 2012 tsaiyuan.hsu + * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" + * resolve build waring for "WNM_UNIT_TEST not defined".. + * + * 06 04 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * discussed with WH, privacy bit in associate response is not necessary to be checked, and identified as association failure when mismatching with beacon/probe response + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 23 2011 cp.wu + * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection + * add compile option to disable beacon content change detection. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 10 28 2011 cp.wu + * [MT6620 Wi-Fi][Win32 Driver] Enable 5GHz support as default + * enable 5GHz as default for DaVinci trunk and V2.1 driver release . + * + * 10 18 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * surpress compiler warning for MT6628 build + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * enable divided firmware downloading. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 28 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * enlarge window size only by 4. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 12 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. + * + * 08 09 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS definition for MT6620. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Refine compile flag. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 06 24 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC[WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * increase RX buffer number to have a 2:1 ping-pong ratio + * + * 06 23 2011 eddie.chen + * [WCXRP00000810] [MT5931][DRV/FW] Adjust TxRx Buffer number and Rx buffer size + * 1. Different TX RX buffer + * 2. Enlarge RX buffer and increase the number 8->11 + * 3. Seperate the WINSZIE and RX buffer number + * 4. Fix RX maximum size in MAC + * + * 06 20 2011 terry.wu + * NULL + * Add BoW Rate Limitation. + * + * 06 17 2011 terry.wu + * NULL + * . + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add compile flag for persistent group support. + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Limit AIS to fixed channel same with BOW + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * Enable RX STBC capability + * + * 04 11 2011 george.huang + * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF + * . + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. correction: RX aggregation is not limited to SDIO but for all host interface options + * 2. add forward declarations for DBG-only symbols + * + * 04 06 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port + * 2. update perm_addr as well for MAC address + * 3. not calling check_mem_region() anymore for eHPI + * 4. correct MSC_CS macro for 0-based notation + * + * 04 01 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface + * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR + * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 18 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the Anti_piracy check at driver . + * + * 03 17 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * enable roaming feature. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 03 01 2011 george.huang + * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames + * Fix compile issue + * + * 02 25 2011 george.huang + * [WCXRP00000497] [MT6620 Wi-Fi][FW] Change default UAPSD AC assignment + * Assign all AC default to be U-APSD enabled. + * + * 02 14 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * Let the privacy check at hotspot mode default enable. + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 02 08 2011 cp.wu + * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number + * change version number to v1.2.0.0 for preparing v1.2 software package release. + * + * 02 01 2011 yarco.yang + * [WCXRP00000417] [MT6620 Driver] Chnage CFG_HANDLE_IST_IN_SDIO_CALLBACK from 1 to 0 for Interoperability + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 19 2011 wh.su + * [WCXRP00000370] [MT6620 Wi-Fi][Driver] Disable Rx RDG for workaround pre-N ccmp issue + * Not announce support Rx RDG for wokaround pre-N ccmp construct AAD issue.. + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information + * fill mac header length information for 802.1x frames. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW only for Linux. + * + * 01 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Enable BOW and 4 physical links. + * + * 01 08 2011 yuche.tsai + * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, but the SSID length is still invalid. + * Modify CFG_SLT_SUPPORT default value. + * + * 01 08 2011 yuche.tsai + * [WCXRP00000341] [MT6620][SLT] Create Branch for SLT SW. + * Update configure flag. + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 15 2010 yuche.tsai + * NULL + * Update SLT Descriptor number configure in driver. + * + * 12 13 2010 chinglan.wang + * NULL + * Add WPS 1.0 feature flag to enable the WPS 1.0 function. + * + * 11 23 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Enable PM function by default + * + * 11 15 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * use config.mk WAPI config define. + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * use the config.mk define. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add option for enable/disable TX PWR gain adjustment (default: off) + * + * 10 20 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * enable the WAPI compiling flag as default + * + * 10 19 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 14 2010 wh.su + * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * Add a define CFG_TEST_ANDROID_DIRECT_GO compiling flag + * + * 10 08 2010 cm.chang + * NULL + * Remove unused compiling flags (TX_RDG and TX_SGI) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 05 2010 yarco.yang + * [WCXRP00000082] [MT6620 Wi-Fi][Driver]High throughput performance tuning + * Change CFG_IST_LOOP_COUNT from 2 to 1 to reduce unnecessary SDIO bus access + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 20 2010 cm.chang + * NULL + * Disable RX STBC by BB HEC based on MT6620E1_PHY_BUG v05.docx + * + * 09 17 2010 chinglan.wang + * NULL + * Add performance test option + * + * 09 10 2010 chinglan.wang + * NULL + * Modify for Software Migration Phase 2.10 for E2 FPGA + * + * 09 07 2010 yuche.tsai + * NULL + * Add a CFG for max common IE buffer size. + * + * 09 01 2010 cp.wu + * NULL + * restore configuration as before. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 chinglan.wang + * NULL + * Enable the MT6620_FPGA_BWCS value. + * + * 08 30 2010 chinglan.wang + * NULL + * Disable the FW encryption. + * + * 08 27 2010 chinglan.wang + * NULL + * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 cp.wu + * NULL + * add option for enabling AIS 5GHz scan + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 23 2010 chinghwa.yu + * NULL + * Disable BOW Test. + * + * 08 23 2010 jeffrey.chang + * NULL + * fix config.h typo + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 21 2010 jeffrey.chang + * NULL + * 1) add sdio two setting + * 2) bug fix of sdio glue + * + * 08 09 2010 wh.su + * NULL + * let the firmware download default enabled. + * + * 08 07 2010 wh.su + * NULL + * adding the privacy related code for P2P network + * + * 08 05 2010 yuche.tsai + * NULL + * Add a configure flag for P2P unitest. + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 cp.wu + * + * 1) enable Ad-Hoc + * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 yuche.tsai + * + * Add for SLT support. + * + * 07 16 2010 cp.wu + * + * remove work-around in case SCN is not available. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * for first connection, if connecting failed do not enter into scan state. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add SCN compilation option. + * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * set default compiling flag for security disable. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add config option for cfg80211. + * + * 05 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * set ATIMwindow default value to zero. + * + * 05 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add option for FPGA_BWCS & FPGA_V5 + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) enable CMD/EVENT ver 0.9 definition. + * 2) abandon use of ENUM_MEDIA_STATE + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change firmware name to WIFI_RAM_CODE. + * + * 05 07 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * disable bt-over-wifi configuration, turn it on after firmware finished implementation + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * re-enable power management + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable TCP/IP checksum offloading by default. + * + * 04 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * set CFG_ENABLE_FULL_PM to 1 as default to + * 1) acquire own before hardware access + * 2) set own back after hardware access + * + * 04 15 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * change firmware name + * + * 04 07 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * disable RX-enhanced response temporally, it seems the CQ is not resolved yet. + * + * 04 06 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * re-enable RX enhanced mode as WPD00003827 is resolved. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * turn off RX_ENHANCE mode by default. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) eliminate unused definitions + * * 2) ready bit will be polled for limited iteration + * + * 04 02 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * firmware download: Linux uses different firmware path + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load adress & start address are now configured from config.h + * * due to the different configurations on FPGA and ASIC + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add options for full PM support. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * turn on FW-DOWNLOAD as default for release. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 05 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * change CFG_NUM_OF_QM_RX_PKT_NUM to 120 + * + * 03 04 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * . + * + * 03 04 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * increase RX buffer number to avoid RX buffer starvation. + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed the number of STA_RECs to 20 + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * and result is retrieved by get ATInfo instead + * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-16 22:12:28 GMT mtk02752 +** enable interrupt enhanced response, TX/RX Aggregation as default +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:38:43 GMT mtk02752 +** eliminate compile options which are obsolete or for emulation purpose +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 13:56:26 GMT MTK02468 +** Added RX buffer reordering configurations +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-12-04 12:09:09 GMT mtk02752 +** once enhanced intr/rx reponse is taken, RX must be access in aggregated basis +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 17:54:50 GMT mtk02752 +** correct a typo +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:47 GMT mtk01084 +** add defines +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:33:37 GMT mtk02752 +** add coalescing buffer definition for SD1_SD3_DATAPATH_INTEGRATION +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 20:32:40 GMT mtk02752 +** add CFG_TX_MAX_PKT_NUM for limiting queued TX packet +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 13:34:44 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION define for source control +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 13:54:11 GMT mtk01084 +** enable INT enhance mode by default +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-30 18:17:14 GMT mtk01084 +** add new define +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-10-29 19:47:36 GMT mtk01084 +** not use HIF loopback mode +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-13 21:58:33 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-09-09 17:26:08 GMT mtk01084 +** add CFG_TEST_WITH_MT5921 +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:02:30 GMT mtk01426 +** Update CFG_RX_COALESCING_BUFFER_SIZE +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-21 09:35:51 GMT mtk01461 +** Add CFG_TX_DBG_MGT_BUF to debug MGMT Buffer depth +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:52:21 GMT mtk01426 +** Add OOB_DATA_PRE_FIXED_LEN define +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-08 16:51:08 GMT mtk01084 +** update for FW download part +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:33:37 GMT mtk01461 +** Add SW pre test flag CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 00:29:18 GMT mtk01461 +** Fix CFG_COALESCING_BUFFER_SIZE if enable the CFG_TX_FRAGMENT +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-18 20:58:34 GMT mtk01426 +** Add CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-17 20:17:36 GMT mtk01426 +** Add CMD/Response related configure +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:21 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:21 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#ifndef MT6620 +#define MT6620 +#endif + +#ifdef MT5931 +#undef MT5931 +#endif + +#ifdef MT6628 +#undef MT6628 +#endif + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//2 Flags for OS capability + +#ifdef LINUX + #ifdef CONFIG_X86 + #define MTK_WCN_HIF_SDIO 0 + #else + #define MTK_WCN_HIF_SDIO 1 + #endif +#else + #define MTK_WCN_HIF_SDIO 0 +#endif + +#if (CFG_SUPPORT_AEE == 1) + #define CFG_ENABLE_AEE_MSG 1 +#else + #define CFG_ENABLE_AEE_MSG 0 +#endif + +//2 Flags for Driver Features +#define CFG_TX_FRAGMENT 1 /*!< 1: Enable TX fragmentation + 0: Disable */ +#define CFG_SUPPORT_PERFORMANCE_TEST 0 /*Only for performance Test*/ + +#define CFG_COUNTRY_CODE NULL //"US" + +#ifndef LINUX + #define CFG_FW_FILENAME L"WIFI_RAM_CODE" + #define CFG_FW_FILENAME_E6 L"WIFI_RAM_CODE_E6" +#else + #define CFG_FW_FILENAME "WIFI_RAM_CODE" +#endif + +#define CFG_SUPPORT_802_11D 1 /*!< 1(default): Enable 802.11d + 0: Disable */ + +#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ +#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ + + +#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ + +/*------------------------------------------------------------------------------ + * SLT Option + *------------------------------------------------------------------------------ + */ +#define CFG_SLT_SUPPORT 0 + + +#ifdef NDIS60_MINIPORT + #define CFG_NATIVE_802_11 1 + + #define CFG_TX_MAX_PKT_SIZE 2304 + #define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 /* !< 1: Enable TCP/IP header checksum offload + 0: Disable */ + #define CFG_TCP_IP_CHKSUM_OFFLOAD 0 + #define CFG_WHQL_DOT11_STATISTICS 1 + #define CFG_WHQL_ADD_REMOVE_KEY 1 + #define CFG_WHQL_CUSTOM_IE 1 + #define CFG_WHQL_SAFE_MODE_ENABLED 1 + +#else + #define CFG_TCP_IP_CHKSUM_OFFLOAD 1 /* !< 1: Enable TCP/IP header checksum offload + 0: Disable */ + #define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 + #define CFG_TX_MAX_PKT_SIZE 1600 + #define CFG_NATIVE_802_11 0 +#endif + + +//2 Flags for Driver Parameters +/*------------------------------------------------------------------------------ + * Flags for EHPI Interface in Colibri Platform + *------------------------------------------------------------------------------ + */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 /*!< 1: Do workaround for faster bus timing + 0(default): Disable */ + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint + #define _HIF_SDIO 1 +#endif + +#define CFG_SDIO_INTR_ENHANCE 1 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode + 0: Disable */ +#define CFG_SDIO_RX_ENHANCE 0 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode + 0: Disable */ +#define CFG_SDIO_TX_AGG 1 /*!< 1: Enable SDIO TX enhance mode(Multiple frames in single BLOCK CMD) + 0(default): Disable */ + +#define CFG_SDIO_RX_AGG 1 /*!< 1: Enable SDIO RX enhance mode(Multiple frames in single BLOCK CMD) + 0(default): Disable */ + +#if (CFG_SDIO_RX_AGG == 1) && (CFG_SDIO_INTR_ENHANCE == 0) + #error "CFG_SDIO_INTR_ENHANCE should be 1 once CFG_SDIO_RX_AGG equals to 1" +#elif (CFG_SDIO_INTR_ENHANCE == 1 || CFG_SDIO_RX_ENHANCE == 1) && (CFG_SDIO_RX_AGG == 0) + #error "CFG_SDIO_RX_AGG should be 1 once CFG_SDIO_INTR_ENHANCE and/or CFG_SDIO_RX_ENHANCE equals to 1" +#endif + +#define CFG_SDIO_MAX_RX_AGG_NUM 0 /*!< 1: Setting the maximum RX aggregation number + 0(default): no limited */ + +#ifdef WINDOWS_CE + #define CFG_SDIO_PATHRU_MODE 1 /*!< 1: Suport pass through (PATHRU) mode + 0: Disable */ +#else + #define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ +#endif + +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) + #define MT6620_FPGA_BWCS 0 + #define MT6620_FPGA_V5 0 + + #if (MT6620_FPGA_BWCS == 1) && (MT6620_FPGA_V5 == 1) + #error + #endif + + #if (MTK_WCN_HIF_SDIO == 1) + #define CFG_MULTI_ECOVER_SUPPORT 1 + #elif !defined(LINUX) + #define CFG_MULTI_ECOVER_SUPPORT 1 + #else + #define CFG_MULTI_ECOVER_SUPPORT 0 + #endif + + #define CFG_ENABLE_CAL_LOG 0 + #define CFG_REPORT_RFBB_VERSION 0 +#elif defined(MT5931) + +#define CFG_MULTI_ECOVER_SUPPORT 0 +#define CFG_ENABLE_CAL_LOG 0 +#define CFG_REPORT_RFBB_VERSION 0 + +#elif defined(MT6628) + +#define CFG_MULTI_ECOVER_SUPPORT 0 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#endif + +#define CFG_CHIP_RESET_SUPPORT 1 + + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) && (MT6620_FPGA_BWCS == 0) && (MT6620_FPGA_V5 == 0) + #define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#else + #define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for driver version + *------------------------------------------------------------------------------ + */ +#define CFG_DRV_OWN_VERSION ((UINT_16)((NIC_DRIVER_MAJOR_VERSION << 8) | (NIC_DRIVER_MINOR_VERSION))) +#define CFG_DRV_PEER_VERSION ((UINT_16)0x0000) + + +/*------------------------------------------------------------------------------ + * Flags for TX path which are OS dependent + *------------------------------------------------------------------------------ + */ +/*! NOTE(Kevin): If the Network buffer is non-scatter-gather like structure(without + * NETIF_F_FRAGLIST in LINUX), then we can set CFG_TX_BUFFER_IS_SCATTER_LIST to "0" + * for zero copy TX packets. + * For scatter-gather like structure, we set "1", driver will do copy frame to + * internal coalescing buffer before write it to FIFO. + */ +#if defined(LINUX) + #define CFG_TX_BUFFER_IS_SCATTER_LIST 1 /*!< 1: Do frame copy before write to TX FIFO. + Used when Network buffer is scatter-gather. + 0(default): Do not copy frame */ +#else /* WINDOWS/WINCE */ + #define CFG_TX_BUFFER_IS_SCATTER_LIST 1 +#endif /* LINUX */ + + +#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST + #define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE * NIC_TX_BUFF_SUM) +#else + #define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 256 + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*! Maximum number of associated STAs */ +#define CFG_NUM_OF_STA_RECORD 20 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*! Max. descriptor number - sync. with firmware */ +#if CFG_SLT_SUPPORT +#define CFG_NUM_OF_RX0_HIF_DESC 42 +#else +#define CFG_NUM_OF_RX0_HIF_DESC 16 +#endif +#define CFG_NUM_OF_RX1_HIF_DESC 2 + +/*! Max. buffer hold by QM */ +#define CFG_NUM_OF_QM_RX_PKT_NUM 120 + +/*! Maximum number of SW RX packet buffer */ +#define CFG_RX_MAX_PKT_NUM ((CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC) * 3 \ + + CFG_NUM_OF_QM_RX_PKT_NUM) + +#define CFG_RX_REORDER_Q_THRESHOLD 8 + +#ifndef LINUX +#define CFG_RX_RETAINED_PKT_THRESHOLD (CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC + CFG_NUM_OF_QM_RX_PKT_NUM) +#else +#define CFG_RX_RETAINED_PKT_THRESHOLD 0 +#endif + +/*! Maximum RX packet size, if exceed this value, drop incoming packet */ +/* 7.2.3 Maganement frames */ +#define CFG_RX_MAX_PKT_SIZE ( 28 + 2312 + 12 /*HIF_RX_HEADER_T*/ ) //TODO: it should be 4096 under emulation mode + +/*! Minimum RX packet size, if lower than this value, drop incoming packet */ +#define CFG_RX_MIN_PKT_SIZE 10 /*!< 802.11 Control Frame is 10 bytes */ + +#if CFG_SDIO_RX_AGG + /* extra size for CS_STATUS and enhanced response */ + #define CFG_RX_COALESCING_BUFFER_SIZE ((CFG_NUM_OF_RX0_HIF_DESC + 1) \ + * CFG_RX_MAX_PKT_SIZE) +#else + #define CFG_RX_COALESCING_BUFFER_SIZE (CFG_RX_MAX_PKT_SIZE) +#endif + +/*! RX BA capability */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 8 +#define CFG_RX_BA_MAX_WINSIZE 16 +#define CFG_RX_BA_INC_SIZE 4 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +#define CFG_RESPONSE_POLLING_TIMEOUT 512 + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 64 + +#define CFG_MAX_COMMON_IE_BUF_LEN (1500 * CFG_MAX_NUM_BSS_LIST) / 3 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*! Maximum number of STA records */ +#define CFG_MAX_NUM_STA_RECORD 32 + + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 + +#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH + +#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 + +#define CFG_INIT_UAPSD_AC_BMP 0//(BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +//#define CFG_SUPPORT_WAPI 0 +#define CFG_SUPPORT_WPS 1 +#define CFG_SUPPORT_WPS2 1 + +/*------------------------------------------------------------------------------ + * 802.11i RSN Pre-authentication PMKID cahce maximun number + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_PMKID_CACHE 16 /*!< max number of PMKID cache + 16(default) : The Max PMKID cache */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Ad-Hoc + *------------------------------------------------------------------------------ + */ +#define CFG_INIT_ADHOC_FREQ (2462000) +#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG +#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) +#define CFG_INIT_ADHOC_ATIM_WINDOW (0) + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#if defined(_HIF_SDIO) && defined(WINDOWS_CE) + #define CFG_IST_LOOP_COUNT 1 +#else + #define CFG_IST_LOOP_COUNT 1 +#endif /* _HIF_SDIO */ + +#define CFG_INT_WRITE_CLEAR 0 + +#if defined(LINUX) +#define CFG_DBG_GPIO_PINS 0 /* if 1, use MT6516 GPIO pin to log TX behavior */ +#endif + +//2 Flags for Driver Debug Options +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying following flags. + *------------------------------------------------------------------------------ + */ +#define CFG_DBG_MGT_BUF 1 /*!< 1: Debug statistics usage of MGMT Buffer + 0: Disable */ + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_STARTUP_DEBUG 0 + +#define CFG_RX_PKTS_DUMP 1 + +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 +#define CFG_ENABLE_FW_ENCRYPTION 1 + +#if defined(MT6620) || defined(MT6628) + #define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION 0 + #define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 1 +#else + #define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION 0 + #define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 0 +#endif + + + +#if defined(MT6620) + #if MT6620_FPGA_BWCS + #define CFG_FW_LOAD_ADDRESS 0x10014000 + #define CFG_OVERRIDE_FW_START_ADDRESS 0 + #define CFG_FW_START_ADDRESS 0x10014001 + #elif MT6620_FPGA_V5 + #define CFG_FW_LOAD_ADDRESS 0x10008000 + #define CFG_OVERRIDE_FW_START_ADDRESS 0 + #define CFG_FW_START_ADDRESS 0x10008001 + #else + #define CFG_FW_LOAD_ADDRESS 0x10008000 + #define CFG_OVERRIDE_FW_START_ADDRESS 0 + #define CFG_FW_START_ADDRESS 0x10008001 + #endif +#elif defined(MT5931) + #define CFG_FW_LOAD_ADDRESS 0xFF900000 + #define CFG_FW_START_ADDRESS 0x00000000 +#elif defined(MT6628) + #define CFG_FW_LOAD_ADDRESS 0x00060000 + #define CFG_OVERRIDE_FW_START_ADDRESS 0 + #define CFG_FW_START_ADDRESS 0x00060000 +#endif + + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX + #ifdef CONFIG_X86 + #define CFG_ENABLE_BT_OVER_WIFI 0 + #else + #define CFG_ENABLE_BT_OVER_WIFI 1 + #endif +#else + #define CFG_ENABLE_BT_OVER_WIFI 0 +#endif + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_TEST 0 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 0 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +#ifdef LINUX + #ifdef CONFIG_X86 + #define CFG_ENABLE_WIFI_DIRECT 0 + #define CFG_SUPPORT_802_11W 0 + #else + #define CFG_ENABLE_WIFI_DIRECT 1 + #define CFG_SUPPORT_802_11W 0 /*!< 0(default): Disable 802.11W */ + #endif +#else + #define CFG_ENABLE_WIFI_DIRECT 0 + #define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +/*------------------------------------------------------------------------------ + * Configuration Flags (Linux Only) + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_EXT_CONFIG 0 + +/*------------------------------------------------------------------------------ + * Statistics Buffering Mechanism + *------------------------------------------------------------------------------ + */ +#if CFG_SUPPORT_PERFORMANCE_TEST +#define CFG_ENABLE_STATISTICS_BUFFERING 1 +#else +#define CFG_ENABLE_STATISTICS_BUFFERING 0 +#endif +#define CFG_STATISTICS_VALID_CYCLE 2000 +#define CFG_LINK_QUALITY_VALID_PERIOD 5000 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 1 +#define CFG_SUPPORT_AAA 1 + + +#if (defined(MT5931) && defined(LINUX)) +#define CFG_SUPPORT_BCM 1 +#define CFG_SUPPORT_BCM_BWCS 1 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 1 +#else +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 +#endif + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_RSN_MIGRATION 1 + +#define CFG_PRIVACY_MIGRATION 1 + +#define CFG_ENABLE_HOTSPOT_PRIVACY_CHECK 1 + +#define CFG_MGMT_FRAME_HANDLING 1 + +#define CFG_MGMT_HW_ACCESS_REPLACEMENT 0 + +#if CFG_SUPPORT_PERFORMANCE_TEST + +#else + +#endif + +#define CFG_SUPPORT_AIS_5GHZ 1 +#define CFG_SUPPORT_BEACON_CHANGE_DETECTION 0 + +/*------------------------------------------------------------------------------ + * Option for NVRAM and Version Checking + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM 1 +#define CFG_NVRAM_EXISTENCE_CHECK 1 +#define CFG_SW_NVRAM_VERSION_CHECK 1 +#define CFG_SUPPORT_NIC_CAPABILITY 1 + + +/*------------------------------------------------------------------------------ + * CONFIG_TITLE : Stress Test Option + * OWNER : Puff Wen + * Description : For stress test only. DO NOT enable it while normal operation + *------------------------------------------------------------------------------ + */ +#define CFG_STRESS_TEST_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Flags for LINT + *------------------------------------------------------------------------------ + */ +#define LINT_SAVE_AND_DISABLE /*lint -save -e* */ + +#define LINT_RESTORE /*lint -restore */ + +#define LINT_EXT_HEADER_BEGIN LINT_SAVE_AND_DISABLE + +#define LINT_EXT_HEADER_END LINT_RESTORE + +/*------------------------------------------------------------------------------ + * Flags of Features + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_QOS 1 /* Enable/disable QoS TX, AMPDU */ +#define CFG_SUPPORT_AMPDU_TX 1 +#define CFG_SUPPORT_AMPDU_RX 1 +#define CFG_SUPPORT_TSPEC 0 /* Enable/disable TS-related Action frames handling */ +#define CFG_SUPPORT_UAPSD 1 +#define CFG_SUPPORT_UL_PSMP 0 + +#define CFG_SUPPORT_ROAMING 1 /* Roaming System */ +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#if defined(MT5931) +#define CFG_SUPPORT_WHOLE_CHIP_RESET 1 /* for e3 chip only */ +#endif + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 + +#define CFG_SUPPORT_802_11V 0 /* Support 802.11v Wireless Network Management */ +#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (CFG_SUPPORT_802_11V == 0) + #error "CFG_SUPPORT_802_11V should be 1 once CFG_SUPPORT_802_11V_TIMING_MEASUREMENT equals to 1" +#endif +#if (CFG_SUPPORT_802_11V == 0) +#define WNM_UNIT_TEST 0 +#endif + +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 + +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 + +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CONFIG_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h new file mode 100755 index 000000000000..3d5f03e16d0d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h @@ -0,0 +1,517 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/debug.h#1 $ +*/ + +/*! \file debug.h + \brief Definition of SW debugging level. + + In this file, it describes the definition of various SW debugging levels and + assert functions. +*/ + + + +/* +** $Log: debug.h $ + * + * 12 16 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * fixed the Windows DDK free build compiling error. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 07 2011 wh.su + * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * . + * + * 09 23 2010 cp.wu + * NULL + * add BOW index for debugging message and passing compilation + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add one more debug moduel for P2P. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add debug module index for cnm and ais. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-29 19:47:50 GMT mtk01084 +** add emu catagory +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-17 18:12:04 GMT mtk01426 +** Don't use dynamic memory allocate for debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:29 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _DEBUG_H +#define _DEBUG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#ifndef BUILD_QA_DBG +#define BUILD_QA_DBG 0 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" +#if CFG_SUPPORT_XLOG +#include "linux/xlog.h" +#endif + +extern UINT_8 aucDebugModule[]; +extern UINT_32 u4DebugModule; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define debug category (class): + * (1) ERROR (2) WARN (3) STATE (4) EVENT (5) TRACE (6) INFO (7) LOUD (8) TEMP + */ +#define DBG_CLASS_ERROR BIT(0) +#define DBG_CLASS_WARN BIT(1) +#define DBG_CLASS_STATE BIT(2) +#define DBG_CLASS_EVENT BIT(3) +#define DBG_CLASS_TRACE BIT(4) +#define DBG_CLASS_INFO BIT(5) +#define DBG_CLASS_LOUD BIT(6) +#define DBG_CLASS_TEMP BIT(7) +#define DBG_CLASS_MASK BITS(0,7) + + +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" + +#else //Windows +#define DBG_PRINTF_64BIT_DEC "I64d" + +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Define debug module index */ +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* For driver initial */ + DBG_HAL_IDX, /* For HAL(HW) Layer */ + DBG_INTR_IDX, /* For Interrupt */ + DBG_REQ_IDX, + DBG_TX_IDX, + DBG_RX_IDX, + DBG_RFTEST_IDX, /* For RF test mode*/ + DBG_EMU_IDX, /* Developer specific */ + + DBG_SW1_IDX, /* Developer specific */ + DBG_SW2_IDX, /* Developer specific */ + DBG_SW3_IDX, /* Developer specific */ + DBG_SW4_IDX, /* Developer specific */ + + DBG_HEM_IDX, /* HEM */ + DBG_AIS_IDX, /* AIS */ + DBG_RLM_IDX, /* RLM */ + DBG_MEM_IDX, /* RLM */ + DBG_CNM_IDX, /* CNM */ + DBG_RSN_IDX, /* RSN */ + DBG_BSS_IDX, /* BSS */ + DBG_SCN_IDX, /* SCN */ + DBG_SAA_IDX, /* SAA */ + DBG_AAA_IDX, /* AAA */ + DBG_P2P_IDX, /* P2P */ + DBG_QM_IDX, /* QUE_MGT */ + DBG_SEC_IDX, /* SEC */ + DBG_BOW_IDX, /* BOW */ + DBG_WAPI_IDX, /* WAPI */ + DBG_ROAMING_IDX, /* ROAMING */ + + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; + +//XLOG +//#define XLOG_DBG_MODULE_IDX 28 /* DBG_MODULE_NUM */ +//#if (XLOG_DBG_MODULE_IDX != XLOG_DBG_MODULE_IDX) +//#error "Please modify the DBG_MODULE_NUM and make sure this include at XLOG" +//#endif + +/* Define who owns developer specific index */ +#define DBG_YARCO_IDX DBG_SW1_IDX +#define DBG_KEVIN_IDX DBG_SW2_IDX +#define DBG_CMC_IDX DBG_SW3_IDX +#define DBG_GEORGE_IDX DBG_SW4_IDX + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Debug print format string for the OS system time */ +#define OS_SYSTIME_DBG_FORMAT "0x%08x" + +/* Debug print argument for the OS system time */ +#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) + +/* Debug print format string for the MAC Address */ +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], \ + ((PUINT_8)a)[3], ((PUINT_8)a)[4], ((PUINT_8)a)[5] + +/* The pre-defined format to dump the value of a varaible with its name shown. */ +#define DUMPVAR(variable, format) (#variable " = " format "\n", variable) + +/* The pre-defined format to dump the MAC type value with its name shown. */ +#define DUMPMACADDR(addr) (#addr " = " MACSTR "\n", MAC2STR(addr)) + + +/* Basiclly, we just do renaming of KAL functions although they should + * be defined as "Nothing to do" if DBG=0. But in some compiler, the macro + * syntax does not support #define LOG_FUNC(x,...) + * + * A caller shall not invoke these three macros when DBG=0. + */ +#define LOG_FUNC_TIME kalPrint +#define LOG_FUNC kalPrint + +#if DBG + + #define TMP_BUF_LEN 256 + #define TMP_WBUF_LEN (TMP_BUF_LEN * 2) + + extern PINT_16 g_wbuf_p; + extern PINT_8 g_buf_p; + + /* If __FUNCTION__ is already defined by compiler, we just use it. */ + #if defined(__FUNCTION__) + #define DEBUGFUNC(_Func) + #else + #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func; + #endif + + /* The following macros are used for future debug message. */ + /* TODO(Kevin): We should remove INITLOG/ERRORLOG/WARNLOG macro sooner or later */ + #define INITLOG(_Fmt) \ + { \ + if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_TRACE) { \ + LOG_FUNC("%s: ", __FUNCTION__); \ + LOG_FUNC _Fmt; \ + } \ + } + + #define ERRORLOG(_Fmt) \ + { \ + if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_ERROR) { \ + LOG_FUNC("**Error[%s:%d]-", __FILE__, __LINE__); \ + LOG_FUNC _Fmt; \ + } \ + } + + #define WARNLOG(_Fmt) \ + { \ + if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_WARN) { \ + LOG_FUNC("**Warning[%s:%d]-", __FILE__, __LINE__); \ + LOG_FUNC _Fmt; \ + } \ + } + + /*lint -save -e960 Multiple use of '#/##' */ + #define DBGLOG(_Module, _Class, _Fmt) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + if (DBG_CLASS_##_Class == DBG_CLASS_ERROR) { \ + LOG_FUNC_TIME("**Error[%s:%d]-", __FILE__, __LINE__); \ + LOG_FUNC("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \ + } \ + else if (DBG_CLASS_##_Class == DBG_CLASS_WARN) { \ + LOG_FUNC_TIME("**Warning[%s:%d]-", __FILE__, __LINE__); \ + LOG_FUNC("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \ + } \ + else if (DBG_CLASS_##_Class == DBG_CLASS_EVENT) { \ + } \ + else { \ + LOG_FUNC_TIME("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \ + } \ + LOG_FUNC _Fmt; \ + } \ + } + + #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __FUNCTION__); \ + dumpMemory8((PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + + #define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __FUNCTION__); \ + dumpMemory32((PUINT_32) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + /*lint -restore */ + + /*lint -save -e961 use of '#undef' is discouraged */ + #undef ASSERT + /*lint -restore */ + + #ifdef _lint + #define ASSERT(_exp) \ + { \ + if (!(_exp)) {do {} while (1);} \ + } + #else + #define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } + #endif /* _lint */ + + #define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } + + #define DISP_STRING(_str) _str + +#else /* !DBG */ + + #define DEBUGFUNC(_Func) + #define INITLOG(_Fmt) + #define ERRORLOG(_Fmt) + #define WARNLOG(_Fmt) + +#if defined(LINUX) + #define DBGLOG(_Module, _Class, _Fmt) \ + { \ + _Module##_##_Class##_LOGFUNC _Fmt; \ + } +#else + #define DBGLOG(_Module, _Class, _Fmt) +#endif + +#if CFG_SUPPORT_XLOG + #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + _Module##_##_Class##_LOGFUNC (__FUNCTION__);\ + _Module##_##_Class##_LOGDUMP8(_StartAddr, _Length); \ + } +#else + #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#endif + #define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) + + #undef ASSERT + +#if BUILD_QA_DBG + #if defined(LINUX) /* For debugging in Linux w/o GDB */ + #define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } + + #define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } + #else + #ifdef WINDOWS_CE + #define UNICODE_TEXT(_msg) TEXT(_msg) + #define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + TCHAR rUbuf[256]; \ + kalBreakPoint(); \ + _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ + UNICODE_TEXT(__FILE__), \ + __LINE__, \ + UNICODE_TEXT(#_exp)); \ + MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ + } \ + } + + #define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + TCHAR rUbuf[256]; \ + kalBreakPoint(); \ + _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ + UNICODE_TEXT(__FILE__), \ + __LINE__, \ + UNICODE_TEXT(#_exp)); \ + MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ + } \ + } + #else + #define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + kalBreakPoint(); \ + } \ + } + + #define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + kalBreakPoint(); \ + } \ + } + #endif /* WINDOWS_CE */ + #endif /* LINUX */ +#else + #define ASSERT(_exp) + #define ASSERT_REPORT(_exp, _fmt) +#endif /* BUILD_QA_DBG */ + + #define DISP_STRING(_str) "" + +#endif /* DBG */ + +#if CFG_STARTUP_DEBUG + #if defined(LINUX) +#define DBGPRINTF kalPrint + #else +#define DBGPRINTF DbgPrint + #endif +#else +#define DBGPRINTF(...) +#endif + + +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUC_INSPECTING_ASSERT +#define DATA_STRUC_INSPECTING_ASSERT(expr) \ + switch (0) {case 0: case (expr): default:;} +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if DBG +VOID +dumpMemory8 ( + IN PUINT_8 pucStartAddr, + IN UINT_32 u4Length + ); + +VOID +dumpMemory32 ( + IN PUINT_32 pu4StartAddr, + IN UINT_32 u4Length + ); +#elif CFG_SUPPORT_XLOG +VOID +dumpMemory8 ( + IN UINT_32 log_level, + IN PUINT_8 pucStartAddr, + IN UINT_32 u4Length + ); +#endif /* DBG */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _DEBUG_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h new file mode 100755 index 000000000000..deefb031a2e5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h @@ -0,0 +1,414 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/link.h#1 $ +*/ + +/*! \file link.h + \brief Definition for simple doubly linked list operations. + + In this file we define the simple doubly linked list data structure and its + operation MACROs and INLINE functions. +*/ + + + +/* +** $Log: link.h $ + * + * 08 05 2010 yuche.tsai + * NULL + * Modify a MACRO of LINK_FOR_EACH_SAFE for compile error. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833] [MT6620 and MT5931] Driver migration + * . + * + * + * + * + * May 4 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * add WIFI to BORA source control +** \main\maintrunk.MT5921\8 2008-10-16 15:57:11 GMT mtk01461 +** Update driver to fix lint warning +** \main\maintrunk.MT5921\7 2008-08-10 18:47:53 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\6 2007-12-11 00:09:00 GMT mtk01461 +** Add macro for checking valid list +** \main\maintrunk.MT5921\5 2007-11-13 14:27:01 GMT mtk01461 +** Add LINK_IS_INVALID macro +** Revision 1.1.1.1 2007/06/22 08:09:05 MTK01461 +** no message +** +*/ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) // May cause page fault & unalignment issue (data abort) +#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) // Used to verify that nonbody uses non-initialized link entries. + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Simple Doubly Linked List Structures - Entry Part */ +typedef struct _LINK_ENTRY_T { + struct _LINK_ENTRY_T *prNext, *prPrev; +} LINK_ENTRY_T, *P_LINK_ENTRY_T; + +/* Simple Doubly Linked List Structures - List Part */ +typedef struct _LINK_T { + P_LINK_ENTRY_T prNext; + P_LINK_ENTRY_T prPrev; + UINT_32 u4NumElem; +} LINK_T, *P_LINK_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if 0 // No one use it, temporarily mark it for [Lint - Info 773] +#define LINK_ADDR(rLink) { (P_LINK_ENTRY_T)(&(rLink)), (P_LINK_ENTRY_T)(&(rLink)), 0 } + +#define LINK_DECLARATION(rLink) \ + struct _LINK_T rLink = LINK_ADDR(rLink) +#endif + +#define LINK_INITIALIZE(prLink) \ + do { \ + ((P_LINK_T)(prLink))->prNext = (P_LINK_ENTRY_T)(prLink); \ + ((P_LINK_T)(prLink))->prPrev = (P_LINK_ENTRY_T)(prLink); \ + ((P_LINK_T)(prLink))->u4NumElem = 0; \ + } while (0) + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)NULL; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)INVALID_LINK_POISON1; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)(prLink)) + +/* NOTE: We should do memory zero before any LINK been initiated, so we can check + * if it is valid before parsing the LINK. + */ +#define LINK_IS_INVALID(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)NULL) + +#define LINK_IS_VALID(prLink) (((P_LINK_T)(prLink))->prNext != (P_LINK_ENTRY_T)NULL) + + +#define LINK_ENTRY(ptr, type, member) ENTRY_OF(ptr, type, member) + +/* Insert an entry into a link list's head */ +#define LINK_INSERT_HEAD(prLink, prEntry) \ + { \ + linkAdd(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + + +/* Append an entry into a link list's tail */ +#define LINK_INSERT_TAIL(prLink, prEntry) \ + { \ + linkAddTail(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + +/* Peek head entry, but keep still in link list */ +#define LINK_PEEK_HEAD(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prNext, _type, _member) \ + ) + +/* Peek tail entry, but keep still in link list */ +#define LINK_PEEK_TAIL(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prPrev, _type, _member) \ + ) + +/* Get first entry from a link list */ +/* NOTE: We assume the link entry located at the beginning of "prEntry Type", + * so that we can cast the link entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define LINK_REMOVE_HEAD(prLink, prEntry, _P_TYPE) \ + { \ + ASSERT(prLink); \ + if (LINK_IS_EMPTY(prLink)) { \ + prEntry = (_P_TYPE)NULL; \ + } \ + else { \ + prEntry = (_P_TYPE)(((P_LINK_T)(prLink))->prNext); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } \ + } + +/* Assume the link entry located at the beginning of prEntry Type. + * And also decrease the total entry count. + */ +#define LINK_REMOVE_KNOWN_ENTRY(prLink, prEntry) \ + { \ + ASSERT(prLink); \ + ASSERT(prEntry); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prPrev) + +/* Iterate over a link list safe against removal of link entry */ +#define LINK_FOR_EACH_SAFE(prEntry, prNextEntry, prLink) \ + for (prEntry = (prLink)->prNext, prNextEntry = prEntry->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = prNextEntry, prNextEntry = prEntry->prNext) + +/* Iterate over a link list of given type */ +#define LINK_FOR_EACH_ENTRY(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) + +/* Iterate backwards over a link list of given type */ +#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) + +/* Iterate over a link list of given type safe against removal of link entry */ +#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ + prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prNew Pointer of new link head +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +__linkAdd ( + IN P_LINK_ENTRY_T prNew, + IN P_LINK_ENTRY_T prPrev, + IN P_LINK_ENTRY_T prNext + ) +{ + prNext->prPrev = prNew; + prNew->prNext = prNext; + prNew->prPrev = prPrev; + prPrev->prNext = prNew; + + return; +} /* end of __linkAdd() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry after the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +linkAdd ( + IN P_LINK_ENTRY_T prNew, + IN P_LINK_T prLink + ) +{ + __linkAdd(prNew, (P_LINK_ENTRY_T)prLink, prLink->prNext); + + return; +} /* end of linkAdd() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry before the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +linkAddTail ( + IN P_LINK_ENTRY_T prNew, + IN P_LINK_T prLink + ) +{ + __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T)prLink); + + return; +} /* end of linkAddTail() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +__linkDel ( + IN P_LINK_ENTRY_T prPrev, + IN P_LINK_ENTRY_T prNext + ) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; + + return; +} /* end of __linkDel() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list. +* NOTE: the entry is in an initial state. +* +* \param prEntry Specified link head(entry) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +linkDel ( + IN P_LINK_ENTRY_T prEntry + ) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); + + return; +} /* end of linkDel() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* after the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +linkMove ( + IN P_LINK_ENTRY_T prEntry, + IN P_LINK_T prLink + ) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); + + return; +} /* end of linkMove() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* before the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +linkMoveTail ( + IN P_LINK_ENTRY_T prEntry, + IN P_LINK_T prLink + ) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); + + return; +} /* end of linkMoveTail() */ + +#endif /* _LINK_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h new file mode 100755 index 000000000000..1e7630c7c7ee --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h @@ -0,0 +1,251 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/aa_fsm.h#1 $ +*/ + +/*! \file aa_fsm.h + \brief Declaration of functions and finite state machine for SAA/AAA Module. + + Declaration of functions and finite state machine for SAA/AAA Module. +*/ + + + +/* +** $Log: aa_fsm.h $ + * + * 10 13 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS + * 1. short join failure count limit to 2 + * 2. treat join timeout as kind of join failure as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + + +#ifndef _AA_FSM_H +#define _AA_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Retry interval for retransmiting authentication-request MMPDU. */ +#define TX_AUTHENTICATION_RETRY_TIMEOUT_TU 100 // TU. + +/* Retry interval for retransmiting association-request MMPDU. */ +#define TX_ASSOCIATION_RETRY_TIMEOUT_TU 100 // TU. + +/* Wait for a response to a transmitted authentication-request MMPDU. */ +#define DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 // TU. + +/* Wait for a response to a transmitted association-request MMPDU. */ +#define DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU 512 // TU. + +/* The maximum time to wait for JOIN process complete. */ +#define JOIN_FAILURE_TIMEOUT_BEACON_INTERVAL 20 // Beacon Interval, 20 * 100TU = 2 sec. + +/* Retry interval for next JOIN request. */ +#define JOIN_RETRY_INTERVAL_SEC 10 // Seconds + +/* Maximum Retry Count for accept a JOIN request. */ +#define JOIN_MAX_RETRY_FAILURE_COUNT 2 // Times + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_AA_STATE_T { + AA_STATE_IDLE = 0, + SAA_STATE_SEND_AUTH1, + SAA_STATE_WAIT_AUTH2, + SAA_STATE_SEND_AUTH3, + SAA_STATE_WAIT_AUTH4, + SAA_STATE_SEND_ASSOC1, + SAA_STATE_WAIT_ASSOC2, + AAA_STATE_SEND_AUTH2, + AAA_STATE_SEND_AUTH4, // We may not use, because P2P GO didn't support WEP and 11r + AAA_STATE_SEND_ASSOC2, + AA_STATE_RESOURCE, // A state for debugging the case of out of msg buffer. + AA_STATE_NUM +} ENUM_AA_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in saa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_AA_STATE_T eNextState, + IN P_SW_RFB_T prRetainedSwRfb + ); + +WLAN_STATUS +saaFsmSendEventJoinComplete ( + IN P_ADAPTER_T prAdapter, + WLAN_STATUS rJoinStatus, + P_STA_RECORD_T prStaRec, + P_SW_RFB_T prSwRfb + ); + +VOID +saaFsmRunEventStart ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +WLAN_STATUS +saaFsmRunEventTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +VOID +saaFsmRunEventTxReqTimeOut ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +VOID +saaFsmRunEventRxRespTimeOut ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +VOID +saaFsmRunEventRxAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +saaFsmRunEventRxAssoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +saaFsmRunEventRxDeauth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +saaFsmRunEventRxDisassoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +saaFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID +aaaFsmRunEventRxAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +aaaFsmRunEventRxAssoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +aaaFsmRunEventTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AA_FSM_H */ + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h new file mode 100755 index 000000000000..b153256ed6f3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h @@ -0,0 +1,680 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/ais_fsm.h#1 $ +*/ + +/*! \file ais_fsm.h + \brief Declaration of functions and finite state machine for AIS Module. + + Declaration of functions and finite state machine for AIS Module. +*/ + + + +/* +** $Log: ais_fsm.h $ + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 04 25 2011 cp.wu + * [WCXRP00000676] [MT6620 Wi-Fi][Driver] AIS to reduce request channel period from 5 seconds to 2 seconds + * channel interval for joining is shortened to 2 seconds to avoid interruption of concurrent operating network. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 02 22 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach to improve response time for scanning request + * handle SCAN and RECONNECT with a FIFO approach. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 14 2011 cp.wu + * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent + * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. + * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 25 2010 cp.wu + * NULL + * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, RLM/CNM will handle the channel switching when BSS information is updated + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 26 2010 cp.wu + * + * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, just pend it til 5-sec. period finishes + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 cp.wu + * + * separate AIS-FSM states into different cases of channel request. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Refine AIS-FSM by divided into more states + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 23 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * reduce the backgroud ssid idle time min and max value + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * and will send Null frame to diagnose connection + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Support dynamic channel selection + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Media disconnect indication and related postpone functions + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmRunEventJoinComplete() + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Virtual CMD & RESP for testing CMD PATH + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * add aisFsmInitializeConnectionSettings() + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_MGMT_FSM for aisFsmTest() + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function prototype of aisFsmInit() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _AIS_FSM_H +#define _AIS_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_BG_SCAN_INTERVAL_MIN_SEC 2 //30 // exponential to 960 +#define AIS_BG_SCAN_INTERVAL_MAX_SEC 2 //960 // 16min + +#define AIS_DELAY_TIME_OF_DISCONNECT_SEC 10 + +#define AIS_IBSS_ALONE_TIMEOUT_SEC 20 // seconds + +#define AIS_BEACON_TIMEOUT_COUNT_ADHOC 30 +#define AIS_BEACON_TIMEOUT_COUNT_INFRA 10 +#define AIS_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define AIS_BEACON_MAX_TIMEOUT_TU 100 +#define AIS_BEACON_MIN_TIMEOUT_TU 5 +#define AIS_BEACON_MAX_TIMEOUT_VALID TRUE +#define AIS_BEACON_MIN_TIMEOUT_VALID TRUE + +#define AIS_BMC_MAX_TIMEOUT_TU 100 +#define AIS_BMC_MIN_TIMEOUT_TU 5 +#define AIS_BMC_MAX_TIMEOUT_VALID TRUE +#define AIS_BMC_MIN_TIMEOUT_VALID TRUE + +#define AIS_JOIN_CH_GRANT_THRESHOLD 10 +#define AIS_JOIN_CH_REQUEST_INTERVAL 2000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_AIS_STATE_T { + AIS_STATE_IDLE = 0, + AIS_STATE_SEARCH, + AIS_STATE_SCAN, + AIS_STATE_ONLINE_SCAN, + AIS_STATE_LOOKING_FOR, + AIS_STATE_WAIT_FOR_NEXT_SCAN, + AIS_STATE_REQ_CHANNEL_JOIN, + AIS_STATE_JOIN, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_NUM +} ENUM_AIS_STATE_T; + + +typedef struct _MSG_AIS_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; +} MSG_AIS_ABORT_T, *P_MSG_AIS_ABORT_T; + + +typedef struct _MSG_AIS_IBSS_PEER_FOUND_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + P_STA_RECORD_T prStaRec; +} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; + +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; + +typedef struct _AIS_REQ_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_AIS_REQUEST_TYPE_T eReqType; +} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; + + +typedef struct _AIS_FSM_INFO_T { + ENUM_AIS_STATE_T ePreviousState; + ENUM_AIS_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + +#if CFG_SUPPORT_ROAMING + BOOLEAN fgIsRoamingScanPending; +#endif /* CFG_SUPPORT_ROAMING */ + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + P_STA_RECORD_T prTargetStaRec; /* For JOIN Abort */ + + UINT_32 u4SleepInterval; + + TIMER_T rBGScanTimer; + + TIMER_T rIbssAloneTimer; + + TIMER_T rIndicationOfDisconnectTimer; + + TIMER_T rJoinTimeoutTimer; + + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfScanReq; + + UINT_32 u4ChGrantedInterval; + + UINT_8 ucConnTrialCount; + + UINT_8 ucScanSSIDLen; + UINT_8 aucScanSSID[ELEM_MAX_LEN_SSID]; + + UINT_32 u4ScanIELength; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + + /* Pending Request List */ + LINK_T rPendingReqList; + +} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState = (_eNewMediaState)); + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +aisInitializeConnectionSettings ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ); + +VOID +aisFsmInit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmUninit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmStateInit_JOIN ( + IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ); + +BOOLEAN +aisFsmStateInit_RetryJOIN ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +VOID +aisFsmStateInit_IBSS_ALONE ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmStateInit_IBSS_MERGE ( + IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ); + +VOID +aisFsmStateAbort ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucReasonOfDisconnect, + BOOLEAN fgDelayIndication + ); + +VOID +aisFsmStateAbort_JOIN ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmStateAbort_SCAN ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmStateAbort_NORMAL_TR ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmStateAbort_IBSS ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmSteps ( + IN P_ADAPTER_T prAdapter, + ENUM_AIS_STATE_T eNextState + ); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventScanDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +aisFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +aisFsmRunEventJoinComplete ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +aisFsmRunEventFoundIBSSPeer ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmCreateIBSS ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmMergeIBSS ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventChGrant ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmReleaseCh ( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost ( + IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, + BOOLEAN fgDelayIndication + ); + +VOID +aisPostponedEventOfDisconnTimeout ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ); + +VOID +aisUpdateBssInfoForJOIN ( + IN P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + P_SW_RFB_T prAssocRspSwRfb + ); + +VOID +aisUpdateBssInfoForCreateIBSS ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisUpdateBssInfoForMergeIBSS ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +BOOLEAN +aisValidateProbeReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmDisconnect ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgDelayIndication + ); + + +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID +aisBssBeaconTimeout ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +aisDeauthXmitComplete ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +#if CFG_SUPPORT_ROAMING +VOID +aisFsmRunEventRoamingDiscovery ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4ReqScan + ); + +ENUM_AIS_STATE_T +aisFsmRoamingScanResultsUpdate ( + IN P_ADAPTER_T prAdapter + ); + +VOID +aisFsmRoamingDisconnectPrevAP ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prTargetStaRec + ); + +VOID +aisUpdateBssInfoForRoamingAP ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prAssocRspSwRfb + ); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventBGSleepTimeOut ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ); + +VOID +aisFsmRunEventIbssAloneTimeOut ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ); + +VOID +aisFsmRunEventJoinTimeout ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmScanRequest ( + IN P_ADAPTER_T prAdapter, + IN P_PARAM_SSID_T prSsid, + IN PUINT_8 pucIe, + IN UINT_32 u4IeLength + ); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +aisFsmIsRequestPending ( + IN P_ADAPTER_T prAdapter, + IN ENUM_AIS_REQUEST_TYPE_T eReqType, + IN BOOLEAN bRemove + ); + +P_AIS_REQ_HDR_T +aisFsmGetNextRequest ( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +aisFsmInsertRequest ( + IN P_ADAPTER_T prAdapter, + IN ENUM_AIS_REQUEST_TYPE_T eReqType + ); + +VOID +aisFsmFlushRequest ( + IN P_ADAPTER_T prAdapter + ); + + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +VOID +aisTest ( + VOID + ); +#endif /* CFG_TEST_MGMT_FSM */ +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AIS_FSM_H */ + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h new file mode 100755 index 000000000000..1dbb06e73f1c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h @@ -0,0 +1,147 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/assoc.h#1 $ +*/ + +/*! \file assoc.h + \brief This file contains the ASSOC REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: assoc.h $ + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add assocCheckTxReAssocRespFrame() proto type for P2P usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _ASSOC_H +#define _ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in assoc.c */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocSendReAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +WLAN_STATUS +assocCheckTxReAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +WLAN_STATUS +assocCheckTxReAssocRespFrame( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ); + +WLAN_STATUS +assocSendDisAssocFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_16 u2ReasonCode + ); + +WLAN_STATUS +assocProcessRxDisassocFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucBSSID[], + OUT PUINT_16 pu2ReasonCode + ); + +WLAN_STATUS +assocProcessRxAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ); + +WLAN_STATUS +assocSendReAssocRespFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ASSOC_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h new file mode 100755 index 000000000000..6a8bf18b063b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h @@ -0,0 +1,175 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/auth.h#1 $ +*/ + +/*! \file auth.h + \brief This file contains the authentication REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: auth.h $ + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _AUTH_H +#define _AUTH_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in auth.c */ +/*----------------------------------------------------------------------------*/ +VOID +authAddIEChallengeText ( + IN P_ADAPTER_T prAdapter, + IN OUT P_MSDU_INFO_T prMsduInfo + ); + +#if !CFG_SUPPORT_AAA +WLAN_STATUS +authSendAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_16 u2TransactionSeqNum + ); +#else +WLAN_STATUS +authSendAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_SW_RFB_T prFalseAuthSwRfb, + IN UINT_16 u2TransactionSeqNum, + IN UINT_16 u2StatusCode + ); +#endif /* CFG_SUPPORT_AAA */ + +WLAN_STATUS +authCheckTxAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_16 u2TransactionSeqNum + ); + +WLAN_STATUS +authCheckRxAuthFrameTransSeq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +authCheckRxAuthFrameStatus ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_16 u2TransactionSeqNum, + OUT PUINT_16 pu2StatusCode + ); + +VOID +authHandleIEChallengeText ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + P_IE_HDR_T prIEHdr + ); + +WLAN_STATUS +authProcessRxAuth2_Auth4Frame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +authSendDeauthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, + IN UINT_16 u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ); + +WLAN_STATUS +authProcessRxDeauthFrame ( + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucBSSID[], + OUT PUINT_16 pu2ReasonCode + ); + +WLAN_STATUS +authProcessRxAuth1Frame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, + OUT PUINT_16 pu2ReturnStatusCode + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AUTH_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h new file mode 100755 index 000000000000..2e63f9131163 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h @@ -0,0 +1,190 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/bow_fsm.h#1 $ +*/ + +/*! \file bow_fsm.h + \brief Declaration of functions and finite state machine for BOW Module. + + Declaration of functions and finite state machine for BOW Module. +*/ + + + +/* +** $Log: bow_fsm.h $ + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Submit missing BoW header files. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add channel previledge into _BOW_FSM_INFO_T. + * + * 09 16 2010 chinghwa.yu + * NULL + * update bowChangeMediaState. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + */ + +#ifndef _BOW_FSM_H +#define _BOW_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOW_BG_SCAN_INTERVAL_MIN_SEC 2 //30 // exponential to 960 +#define BOW_BG_SCAN_INTERVAL_MAX_SEC 2 //960 // 16min + +#define BOW_DELAY_TIME_OF_DISCONNECT_SEC 10 + +#define BOW_BEACON_TIMEOUT_COUNT_STARTING 10 +#define BOW_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define BOW_BEACON_MAX_TIMEOUT_TU 100 +#define BOW_BEACON_MIN_TIMEOUT_TU 5 +#define BOW_BEACON_MAX_TIMEOUT_VALID TRUE +#define BOW_BEACON_MIN_TIMEOUT_VALID TRUE + +#define BOW_BMC_MAX_TIMEOUT_TU 100 +#define BOW_BMC_MIN_TIMEOUT_TU 5 +#define BOW_BMC_MAX_TIMEOUT_VALID TRUE +#define BOW_BMC_MIN_TIMEOUT_VALID TRUE + +#define BOW_JOIN_CH_GRANT_THRESHOLD 10 +#define BOW_JOIN_CH_REQUEST_INTERVAL 2000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_BOW_STATE_T { + BOW_STATE_IDLE = 0, + BOW_STATE_SEARCH, + BOW_STATE_SCAN, + BOW_STATE_ONLINE_SCAN, + BOW_STATE_LOOKING_FOR, + BOW_STATE_WAIT_FOR_NEXT_SCAN, + BOW_STATE_REQ_CHANNEL_JOIN, + BOW_STATE_REQ_CHANNEL_ALONE, + BOW_STATE_REQ_CHANNEL_MERGE, + BOW_STATE_JOIN, + BOW_STATE_IBSS_ALONE, + BOW_STATE_IBSS_MERGE, + BOW_STATE_NORMAL_TR, + BOW_STATE_NUM +} ENUM_BOW_STATE_T; + +typedef struct _BOW_FSM_INFO_T { + ENUM_BOW_STATE_T ePreviousState; + ENUM_BOW_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + /* Channel Privilege */ + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + BOOLEAN fgIsScanPending; + UINT_32 u4ChGrantedInterval; + + + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + UINT_16 u2BeaconInterval; + + ENUM_BOW_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + ENUM_BOW_STATE_T eForwardState; /* Step to next state if ACTION frame is TX successfully. */ + + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + UINT_8 aucPeerAddress[6]; + + UINT_8 ucRole; + + BOOLEAN fgSupportQoS; + + BOOLEAN fgIsRsponseProbe; /* Indicate if BOW can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfScnMsg; + UINT_8 ucSeqNumOfScanReq; + + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + + /* Timer */ + TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user.*/ + TIMER_T rStartingDiscoveryTimer; + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + TIMER_T rIndicationOfDisconnectTimer; + TIMER_T rChGrantedTimer; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + +} BOW_FSM_INFO_T, *P_BOW_FSM_INFO_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define bowChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)); + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h new file mode 100755 index 000000000000..b7ff943c2763 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h @@ -0,0 +1,353 @@ +/* +** $Id: @(#) bss.h +*/ + +/*! \file "bss.h" + \brief In this file we define the function prototype used in BSS/IBSS. + + The file contains the function declarations and defines for used in BSS/IBSS. +*/ + + + +/* +** $Log: bss.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 02 23 2011 eddie.chen + * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap + * Fix parsing WMM INFO and bmp delivery bitmap definition. + * + * 01 31 2011 george.huang + * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers + * Extend TIM PVB, from 2 to 3 octets. + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 12 2010 kevin.huang + * NULL + * Update bssProcessProbeRequest() and bssSendBeaconProbeResponse() declarations + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add CTRL FLAGS for Probe Response. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Remove unused typedef. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix file merge error + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * and will send Null frame to diagnose connection + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add DTIM count update while TX Beacon + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +#ifndef _BSS_H +#define _BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//NOTE(Kevin): change define for george +//#define MAX_LEN_TIM_PARTIAL_BMP (((MAX_ASSOC_ID + 1) + 7) / 8) /* Required bits = (MAX_ASSOC_ID + 1) */ +#define MAX_LEN_TIM_PARTIAL_BMP ((CFG_STA_REC_NUM + 7) / 8) /* reserve length greater than maximum size of STA_REC */ //obsoleted: Assume we only use AID:1~15 + +/* CTRL FLAGS for Probe Response */ +#define BSS_PROBE_RESP_USE_P2P_DEV_ADDR BIT(0) +#define BSS_PROBE_RESP_INCLUDE_P2P_IE BIT(1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define bssAssignAssocID(_prStaRec) ((_prStaRec)->ucIndex + 1) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +bssComposeNullFrame ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + IN P_STA_RECORD_T prStaRec + ); + +VOID +bssComposeQoSNullFrame ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN BOOLEAN fgSetEOSP + ); + +WLAN_STATUS +bssSendNullFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ); + +WLAN_STATUS +bssSendQoSNullFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ); + + +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +VOID +bssGenerateExtSuppRate_IE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +bssBuildBeaconProbeRespFrameCommonIEs ( + IN P_MSDU_INFO_T prMsduInfo, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucDestAddr + ); + +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF ( + IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, + IN UINT_16 u2BeaconInterval, + IN UINT_16 u2CapInfo + ); + +WLAN_STATUS +bssSendBeaconProbeResponse ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, + IN UINT_32 u4ControlFlags + ); + +WLAN_STATUS +bssProcessProbeRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +bssClearClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo + ); + +VOID +bssAddStaRecToClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec + ); + +VOID +bssRemoveStaRecFromClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec + ); + + +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 ucRCPI + ); + +WLAN_STATUS +ibssCheckCapabilityForAdHocMode ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +ibssInitForAdHoc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo + ); + +WLAN_STATUS +bssUpdateBeaconContent ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +VOID +bssInitForAP ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN BOOLEAN fgIsRateUpdate + ); + +VOID +bssUpdateDTIMCount ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +VOID +bssSetTIMBitmap ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN UINT_16 u2AssocId + ); + + +/*link function to p2p module for txBcnIETable*/ + +/* WMM-2.2.2 WMM ACI to AC coding */ +typedef enum _ENUM_ACI_T { + ACI_BE = 0, + ACI_BK = 1, + ACI_VI = 2, + ACI_VO = 3, + ACI_NUM +} ENUM_ACI_T, *P_ENUM_ACI_T; + +typedef enum _ENUM_AC_PRIORITY_T { + AC_BK_PRIORITY = 0, + AC_BE_PRIORITY, + AC_VI_PRIORITY, + AC_VO_PRIORITY +} ENUM_AC_PRIORITY_T, *P_ENUM_AC_PRIORITY_T; + + +#endif /* _BSS_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h new file mode 100755 index 000000000000..ec41a1155427 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h @@ -0,0 +1,323 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm.h#1 $ +*/ + +/*! \file "cnm.h" + \brief +*/ + + + +/* +** $Log: cnm.h $ + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 01 12 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Provide function to decide if BSS can be activated or not + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 13 2010 cm.chang + * + * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Need bandwidth info when requesting channel privilege + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add a new function to send abort message + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support partial part about cmd basic configuration + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add prototype of cnmFsmEventInit() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_H +#define _CNM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_CH_REQ_TYPE_T { + CH_REQ_TYPE_JOIN, + CH_REQ_TYPE_P2P_LISTEN, + + CH_REQ_TYPE_NUM +} ENUM_CH_REQ_TYPE_T, *P_ENUM_CH_REQ_TYPE_T; + +typedef struct _MSG_CH_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucBSSID[6]; + UINT_8 aucReserved[2]; +} MSG_CH_REQ_T, *P_MSG_CH_REQ_T; + +typedef struct _MSG_CH_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; +} MSG_CH_ABORT_T, *P_MSG_CH_ABORT_T; + +typedef struct _MSG_CH_GRANT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4GrantInterval; /* In unit of ms */ +} MSG_CH_GRANT_T, *P_MSG_CH_GRANT_T; + +typedef struct _MSG_CH_REOCVER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; +} MSG_CH_RECOVER_T, *P_MSG_CH_RECOVER_T; + + +typedef struct _CNM_INFO_T { + UINT_32 u4Reserved; +} CNM_INFO_T, *P_CNM_INFO_T; + +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +typedef struct _DEVICE_TYPE_T { + UINT_16 u2CategoryId; /* Category ID */ + UINT_8 aucOui[4]; /* OUI */ + UINT_16 u2SubCategoryId; /* Sub Category ID */ +} __KAL_ATTRIB_PACKED__ DEVICE_TYPE_T, *P_DEVICE_TYPE_T; +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +cnmInit ( + P_ADAPTER_T prAdapter + ); + +VOID +cnmUninit ( + P_ADAPTER_T prAdapter + ); + +VOID +cnmChMngrRequestPrivilege ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ); + +VOID +cnmChMngrAbortPrivilege ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ); + +VOID +cnmChMngrHandleChEvent ( + P_ADAPTER_T prAdapter, + P_WIFI_EVENT_T prEvent + ); + +BOOLEAN +cnmPreferredChannel ( + P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prBand, + PUINT_8 pucPrimaryChannel, + P_ENUM_CHNL_EXT_T prBssSCO + ); + +BOOLEAN +cnmAisInfraChannelFixed ( + P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prBand, + PUINT_8 pucPrimaryChannel + ); + +VOID +cnmAisInfraConnectNotify ( + P_ADAPTER_T prAdapter + ); + +BOOLEAN +cnmAisIbssIsPermitted ( + P_ADAPTER_T prAdapter + ); + +BOOLEAN +cnmP2PIsPermitted ( + P_ADAPTER_T prAdapter + ); + +BOOLEAN +cnmBowIsPermitted ( + P_ADAPTER_T prAdapter + ); + +BOOLEAN +cnmBss40mBwPermitted ( + P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +__KAL_INLINE__ VOID +cnmMsgDataTypeCheck ( + VOID + ) +{ + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,rMsgHdr) == 0); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,rMsgHdr) == + OFFSET_OF(MSG_CH_RECOVER_T,rMsgHdr)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,ucNetTypeIndex) == + OFFSET_OF(MSG_CH_RECOVER_T,ucNetTypeIndex)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,ucTokenID) == + OFFSET_OF(MSG_CH_RECOVER_T,ucTokenID)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,ucPrimaryChannel) == + OFFSET_OF(MSG_CH_RECOVER_T,ucPrimaryChannel)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,eRfSco) == + OFFSET_OF(MSG_CH_RECOVER_T,eRfSco)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,eRfBand) == + OFFSET_OF(MSG_CH_RECOVER_T,eRfBand)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSG_CH_GRANT_T,eReqType) == + OFFSET_OF(MSG_CH_RECOVER_T,eReqType)); + + return; +} +#endif /* _lint */ + +#endif /* _CNM_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h new file mode 100755 index 000000000000..ae08428153e1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h @@ -0,0 +1,1159 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_mem.h#1 $ +*/ + +/*! \file "cnm_mem.h" + \brief In this file we define the structure of the control unit of + packet buffer and MGT/MSG Memory Buffer. +*/ + + + +/* +** $Log: cnm_mem.h $ + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 03 17 2011 yuche.tsai + * NULL + * Resize the Secondary Device Type array when WiFi Direct is enabled. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Add per STA flow control when STA is in PS mode + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 12 2010 cp.wu + * + * SAA will take a record for tracking request sequence number. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error for P2P related defination. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related fields. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [BORA00000678] [MT6620]WiFi LP integration + * 1. add u8TimeStamp in MSDU_INFO + * 2. move fgIsRxTSFUpdated/fgIsTxTSFUpdated from static to BSS_INFO + * 3. add new member for supporting PM in STA_RECORD, which is for AP PS mode + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support checking of duplicated buffer free + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 19 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fixed MAC RX Desc be overwritten issue + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 10 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support Rx header translation for A-MSDU subframe + * + * 05 07 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * add more sanity check about setting timer + * + * 04 29 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * modify the compiling flag for RAM usage + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Modified some MQM-related data structures (SN counter, TX/RX BA table) + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Added new TX/RX BA tables in STA_REC + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 09 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * [BORA00000644] WiFi phase 4 integration + * Added per-TID SN cache in STA_REC + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support power control + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 11 2010 yuche.tsai + * [BORA00000343][MT6620] Emulation For TX + * . + * + * 03 05 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove Emulation definition + * + * 03 04 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * eliminate HIF_EMULATION in cnm_mem.h + * + * 03 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add cnmStaRecChangeState() declaration. + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning for some emulation flags + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * To store field AMPDU Parameters in STA_REC + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsWmmSupported in STA_RECORD_T. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsUapsdSupported in STA_RECORD_T + * + * 02 13 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added arTspecTable in STA_REC for TSPEC management + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable mgmt buffer debug by default + * + * 02 12 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added BUFFER_SOURCE_BCN + * + * 02 10 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Renamed MSDU_INFO.ucFixedRateIndex as MSDU_INFO.ucFixedRateCode + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 02 02 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added SN info in MSDU_INFO_T + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h + * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem + * 3) use cnmMemAlloc() instead to allocate SRAM buffer + * + * 12 31 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) surpress debug message emitted from hal_hif.c + * 2) add two set of field for recording buffer process time + * + * 12 31 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1. move wifi task initialization from wifi_task.c(rom) to wifi_init.c (TCM) for integrating F/W download later + * * * * * 2. WIFI_Event_Dispatcher() prototype changed to return to suspend mode from normal operation mode + * * * * * 2. HIF emulation logic revised + * + * 12 29 2009 yuche.tsai + * [BORA00000343][MT6620] Emulation For TX + * .Using global buffer declaring by SD1 instead of using another one. + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * MQM: BA handling + * * TXM: Macros updates + * * RXM: Macros/Duplicate Removal updates + * + * 12 24 2009 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 23 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * allocating SRAM for emulation purpose by ruducing MEM_BANK3_BUF_SZ + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove individual DATA_BUF_BLOCK_NUM definition for emulation compiling flagsu1rwduu`wvpghlqg|fh+fmdkb + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support several data buffer banks. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * .For new FPGA memory size + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 17 2009 george.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 17 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Modified the DATA_BLOCK_SIZE from 1620 to 2048 + * + * Dec 16 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_SEC_EMULATION flag + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add HT cap to sta record + * + * Dec 9 2009 mtk02752 + * [BORA00000368] Integrate HIF part into BORA + * add cnmDataPktFree() for emulation loopback purpose + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the buffer for key handshake 1x and cmd key order issue + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * move the tx call back function proto type to typedef.h + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add cnmGetStaRecByAddress() and modify variable in STA_RECORD_T + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the port block flag + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add variables to STA_RECORD_T for assoc/auth + * + * Nov 23 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed the value of STA_WAIT_QUEUE_NUM (from 7 to 5) + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed u2FrameLength from SW_RFB + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed indenting + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Updated MSDU_INFO and SW_RFB + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * update the variable for security + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove the variable to make the compiler ok + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the variable for security module + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo in define of MSG_BUF_BLOCK_SIZE + * + * Nov 13 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Let typedef STA_REC_T precede typedef MSDU_INFO_T and SW_RFB_T + * + * Nov 13 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Modified MSDU_INFO and STA_REC for TXM and MQM + * + * Nov 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename STA_REC_T to STA_RECORD_T and add ucIndex member + * + * Nov 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Make sure ucBufferSource the same offset in MSDU_INFO and SW_RFB + * + * Nov 6 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Nov 5 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comment + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add draft content of MSDU_INFO_T and SW_RFB_T + * + * Oct 30 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 21 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_RX_EMULATION flag + * + * Oct 20 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 9 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added field ucTC to MSDU_INFO_T and field pucHifRxPacket to SW_RFB_T + * + * Oct 8 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_MEM_H +#define _CNM_MEM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef POWER_OF_2 +#define POWER_OF_2(n) BIT(n) +#endif + +/* Size of a basic management buffer block in power of 2 */ +#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 /* 7 to the power of 2 = 128 */ +#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 /* 5 to the power of 2 = 32 */ + +/* Size of a basic management buffer block */ +#define MGT_BUF_BLOCK_SIZE POWER_OF_2(MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCK_SIZE POWER_OF_2(MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Total size of (n) basic management buffer blocks */ +#define MGT_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Number of management buffer block */ +#define MAX_NUM_OF_BUF_BLOCKS 32 /* Range: 1~32 */ + +/* Size of overall management frame buffer */ +#define MGT_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MGT_BUF_BLOCK_SIZE) +#define MSG_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MSG_BUF_BLOCK_SIZE) + + +/* STA_REC related definitions */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE +#define STA_WAIT_QUEUE_NUM 5 /* Number of SW queues in each STA_REC: AC0~AC4 */ +#define SC_CACHE_INDEX_NUM 5 /* Number of SC caches in each STA_REC: AC0~AC4 */ + + +/* P2P related definitions */ +#ifdef CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ +#endif + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if ((MAX_NUM_OF_BUF_BLOCKS > 32) || (MAX_NUM_OF_BUF_BLOCKS <= 0)) + #error > #define MAX_NUM_OF_MGT_BUF_BLOCKS : Out of boundary ! +#elif MAX_NUM_OF_BUF_BLOCKS > 16 + typedef UINT_32 BUF_BITMAP; +#elif MAX_NUM_OF_BUF_BLOCKS > 8 + typedef UINT_16 BUF_BITMAP; +#else + typedef UINT_8 BUF_BITMAP; +#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ + + +/* Control variable of TX management memory pool */ +typedef struct _BUF_INFO_T { + PUINT_8 pucBuf; + +#if CFG_DBG_MGT_BUF + UINT_32 u4AllocCount; + UINT_32 u4FreeCount; + UINT_32 u4AllocNullCount; +#endif /* CFG_DBG_MGT_BUF */ + + BUF_BITMAP rFreeBlocksBitmap; + UINT_8 aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; +} BUF_INFO_T, *P_BUF_INFO_T; + + +/* Wi-Fi divides RAM into three types + * MSG: Mailbox message (Small size) + * BUF: HW DMA buffers (HIF/MAC) + */ +typedef enum _ENUM_RAM_TYPE_T { + RAM_TYPE_MSG = 0, + RAM_TYPE_BUF +} ENUM_RAM_TYPE_T, P_ENUM_RAM_TYPE_T; + +typedef enum _ENUM_BUFFER_SOURCE_T { + BUFFER_SOURCE_HIF_TX0 =0, + BUFFER_SOURCE_HIF_TX1, + BUFFER_SOURCE_MAC_RX, + BUFFER_SOURCE_MNG, + BUFFER_SOURCE_BCN, + BUFFER_SOURCE_NUM +} ENUM_BUFFER_SOURCE_T, *P_ENUM_BUFFER_SOURCE_T; + + +typedef enum _ENUM_SEC_STATE_T { + SEC_STATE_INIT, + SEC_STATE_INITIATOR_PORT_BLOCKED, + SEC_STATE_RESPONDER_PORT_BLOCKED, + SEC_STATE_CHECK_OK, + SEC_STATE_SEND_EAPOL, + SEC_STATE_SEND_DEAUTH, + SEC_STATE_COUNTERMEASURE, + SEC_STATE_NUM +} ENUM_SEC_STATE_T; + +typedef struct _TSPEC_ENTRY_T { + UINT_8 ucStatus; + UINT_8 ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ + UINT_16 u2MediumTime; + UINT_32 u4TsInfo; + //PARAM_QOS_TS_INFO rParamTsInfo; + /* Add other retained QoS parameters below */ +} TSPEC_ENTRY_T, *P_TSPEC_ENTRY_T, TSPEC_TABLE_ENTRY_T, *P_TSPEC_TABLE_ENTRY_T; + +typedef struct _SEC_INFO_T { + + ENUM_SEC_STATE_T ePreviousState; + ENUM_SEC_STATE_T eCurrentState; + + BOOL fg2nd1xSend; + BOOL fgKeyStored; + + UINT_8 aucStoredKey[64]; + + BOOL fgAllowOnly1x; +} SEC_INFO_T, *P_SEC_INFO_T; + +#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 + +#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 // Seconds + +/* Fragment information structure */ +typedef struct _FRAG_INFO_T { + UINT_16 u2NextFragSeqCtrl; + PUINT_8 pucNextFragStart; + P_SW_RFB_T pr1stFrag; + OS_SYSTIME rReceiveLifetimeLimit; /* The receive time of 1st fragment */ +} FRAG_INFO_T, *P_FRAG_INFO_T; + + +/* Define STA record structure */ +struct _STA_RECORD_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucIndex; /* Not modify it except initializing */ + + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ + + /* SAA/AAA */ + ENUM_AA_STATE_T eAuthAssocState; /* Store STATE Value used in SAA/AAA */ + UINT_8 ucAuthAssocReqSeqNum; + + ENUM_STA_TYPE_T eStaType; /* Indicate the role of this STA in + * the network (for example, P2P GO) + */ + + UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ + + UINT_8 ucStaState; /* STATE_1,2,3 */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (may deduced from received BSS_DESC_T) + */ + UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's + * PhyTypeSet and ours. + */ + BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which + * is used to generate some Phy Attribute IE + * (e.g. capability, MIB) during association. + */ + UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type choosen among the + * ucDesiredPhyTypeSet. + */ + + UINT_16 u2CapInfo; /* For Infra Mode, to store Capability Info. from Association Resp(SAA). + * For AP Mode, to store Capability Info. from Association Req(AAA). + */ + UINT_16 u2AssocId; /* For Infra Mode, to store AID from Association Resp(SAA). + * For AP Mode, to store the Assigned AID(AAA). + */ + + UINT_16 u2ListenInterval; /* Listen Interval from STA(AAA) */ + + UINT_16 u2DesiredNonHTRateSet; /* Our Current Desired Rate Set after + * match with STA's Operational Rate Set + */ + + UINT_16 u2OperationalRateSet; /* Operational Rate Set of peer BSS */ + UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ + + BOOLEAN fgIsMerging; /* For IBSS Mode, to indicate that Merge is ongoing */ + + BOOLEAN fgDiagnoseConnection; /* For Infra/AP Mode, to diagnose the Connection with + * this peer by sending ProbeReq/Null frame */ + + /*------------------------------------------------------------------------------------------*/ + /* 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) is true */ + /* They have the same definition with fields of information element */ + /*------------------------------------------------------------------------------------------*/ + UINT_8 ucMcsSet; /* MCS0~7 rate set of peer BSS */ + BOOLEAN fgSupMcs32; /* MCS32 is supported by peer BSS */ + UINT_16 u2HtCapInfo; /* HT cap info field by HT cap IE */ + UINT_8 ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ + UINT_16 u2HtExtendedCap; /* HT extended cap field by HT cap IE */ + UINT_32 u4TxBeamformingCap; /* TX beamforming cap field by HT cap IE */ + UINT_8 ucAselCap; /* ASEL cap field by HT cap IE */ + + UINT_8 ucRCPI; /* RCPI of peer */ + + UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this + * value for setup Listen Interval + * TODO(Kevin): TBD + */ + UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Alogrithm Num used in Authentication(SAA/AAA) */ + BOOLEAN fgIsReAssoc; /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ + + UINT_8 ucTxAuthAssocRetryCount;/* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ + UINT_8 ucTxAuthAssocRetryLimit;/* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ + + UINT_16 u2StatusCode; /* Status of Auth/Assoc Req */ + UINT_16 u2ReasonCode; /* Reason that been Deauth/Disassoc */ + + + P_IE_CHALLENGE_TEXT_T prChallengeText; /* Point to an allocated buffer for storing Challenge Text for Shared Key Authentication */ + + TIMER_T rTxReqDoneOrRxRespTimer;/* For Infra Mode, a timer used to send a timeout event + * while waiting for TX request done or RX response. + */ + + /*------------------------------------------------------------------------------------------*/ + /* Power Management related fields (for STA/ AP/ P2P/ BOW power saving mode) */ + /*------------------------------------------------------------------------------------------*/ + BOOLEAN fgSetPwrMgtBit; /* For Infra Mode, to indicate that outgoing frame need toggle + * the Pwr Mgt Bit in its Frame Control Field. + */ + + BOOLEAN fgIsInPS; /* For AP Mode, to indicate the client PS state(PM). + * TRUE: In PS Mode; FALSE: In Active Mode. */ + + BOOLEAN fgIsInPsPollSP; /* For Infra Mode, to indicate we've sent a PS POLL to AP and start + * the PS_POLL Service Period(LP) + */ + + BOOLEAN fgIsInTriggerSP; /* For Infra Mode, to indicate we've sent a Trigger Frame to AP and start + * the Delivery Service Period(LP) + */ + + UINT_8 ucBmpDeliveryAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + UINT_8 ucBmpTriggerAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + UINT_8 ucUapsdSp; /* Max SP length */ + + /*------------------------------------------------------------------------------------------*/ + + BOOLEAN fgIsRtsEnabled; + + OS_SYSTIME rUpdateTime; /* (4) System Timestamp of Successful TX and RX */ + + OS_SYSTIME rLastJoinTime; /* (4) System Timestamp of latest JOIN process */ + + UINT_8 ucJoinFailureCount; /* Retry Count of JOIN process */ + + LINK_T arStaWaitQueue[STA_WAIT_QUEUE_NUM]; /* For TXM to defer pkt forwarding to MAC TX DMA */ + + UINT_16 au2CachedSeqCtrl[TID_NUM + 1]; /* Duplicate removal for HT STA on a per-TID basis ("+1" is for MMPDU and non-QoS) */ + +#if 0 + /* RXM */ + P_RX_BA_ENTRY_T aprRxBaTable[TID_NUM]; + + /* TXM */ + P_TX_BA_ENTRY_T aprTxBaTable[TID_NUM]; +#endif + + FRAG_INFO_T rFragInfo[MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS]; + + SEC_INFO_T rSecInfo; /* The security state machine */ + + BOOLEAN fgPortBlock; /* The 802.1x Port Control flag */ + + BOOLEAN fgTransmitKeyExist; /* Unicast key exist for this STA */ + + UINT_8 ucWTEntry; + + BOOLEAN fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + BOOLEAN fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + PUINT_8 pucAssocReqIe; + UINT_16 u2AssocReqIeLen; + /*------------------------------------------------------------------------------------------*/ + /* WMM/QoS related fields */ + /*------------------------------------------------------------------------------------------*/ + BOOLEAN fgIsQoS; /* If the STA is associated as a QSTA or QAP (for TX/RX) */ + BOOLEAN fgIsWmmSupported; /* If the peer supports WMM, set to TRUE (for association)*/ + BOOLEAN fgIsUapsdSupported; /* Set according to the scan result (for association) */ + + /*------------------------------------------------------------------------------------------*/ + /* P2P related fields */ + /*------------------------------------------------------------------------------------------*/ +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 u2DevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + UINT_16 u2ConfigMethods; + + UINT_8 ucDeviceCap; + + UINT_8 ucSecondaryDevTypeCount; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + + /*------------------------------------------------------------------------------------------*/ + /* QM related fields */ + /*------------------------------------------------------------------------------------------*/ + + UINT_8 ucFreeQuota; /* Per Sta flow controal. Valid when fgIsInPS is TRUE. Chnage it for per Queue flow control */ + //UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; /* used in future */ + UINT_8 ucFreeQuotaForDelivery; + UINT_8 ucFreeQuotaForNonDelivery; + +#if 1 + /*------------------------------------------------------------------------------------------*/ + /* To be removed, this is to make que_mgt compilation success only */ + /*------------------------------------------------------------------------------------------*/ + /* When this STA_REC is in use, set to TRUE. */ + BOOLEAN fgIsValid; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ + QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* When this STA is in PS Mode, set to TRUE. */ + //BOOLEAN fgIsPS; + + /* When this STA enters Power-Saving, FW will notify the driver with a Session ID */ + UINT_8 ucPsSessionID; + + BOOLEAN fgIsAp; + + /* Reorder Parameter reference table */ + P_RX_BA_ENTRY_T aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; +#endif + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + TIMINGMSMT_PARAM_T rWNMTimingMsmt; +#endif +}; + +#if 0 +/* use nic_tx.h instead */ +/* MSDU_INFO and SW_RFB structure */ +typedef struct _MSDU_INFO_T { + + //4 /* ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + //4 /* -----------------------Non-Common ------------------------- */ + /* TODO: move flags to ucControlFlag */ + + BOOLEAN fgIs1xFrame; /* Set to TRUE for 802.1x frame */ + + /* TXM: For TX Done handling, callback function & parameter (5) */ + BOOLEAN fgIsTxFailed; /* Set to TRUE if transmission failure */ + + PFN_TX_DONE_HANDLER pfTxDoneHandler; + + UINT_64 u8TimeStamp; /* record the TX timestamp */ + + /* TXM: For PS forwarding control (per-STA flow control) */ + UINT_8 ucPsForwardingType; /* Delivery-enabled, non-delivery-enabled, non-PS */ + UINT_8 ucPsSessionID; /* The Power Save session id for PS forwarding control*/ + + /* TXM: For MAC TX DMA operations */ + UINT_8 ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ + BOOLEAN fgNoAck; /* Set to true if Ack is not requred for this packet */ + BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ + UINT_8 ucFragTotalCount; + UINT_8 ucFragFinishedCount; + UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ + BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ + UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ + BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ + + /* TXM: For flushing ACL frames */ + UINT_16 u2PalLLH; /* 802.11 PAL LLH */ + //UINT_16 u2LLH; + UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + BOOLEAN fgIsSnAssigned; + UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ + +} MSDU_INFO_T, *P_MSDU_INFO_T; +#endif + +#if 0 +/* nic_rx.h */ +typedef struct _SW_RFB_T { + + //4 /* ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + //4 /* -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ + PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ + UINT_16 u2HifRxPacketLength; + UINT_8 ucHeaderOffset; + UINT_8 ucHifRxPortIndex; + + UINT_16 u2SequenceControl; + BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + BOOLEAN fgIsBAR; + BOOLEAN fgIsQoSData; + BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + BOOLEAN fgTUChecksumCheckRequired; + BOOLEAN fgIPChecksumCheckRequired; + UINT_8 ucEtherTypeOffset; + +} SW_RFB_T, *P_SW_RFB_T; +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_MSDU_INFO_T +cnmMgtPktAlloc ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Length + ); + +VOID +cnmMgtPktFree ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +cnmMemInit ( + IN P_ADAPTER_T prAdapter + ); + +PVOID +cnmMemAlloc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_RAM_TYPE_T eRamType, + IN UINT_32 u4Length + ); + +VOID +cnmMemFree ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvMemory + ); + +VOID +cnmStaRecInit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +cnmStaRecUninit ( + IN P_ADAPTER_T prAdapter + ); + +P_STA_RECORD_T +cnmStaRecAlloc ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucNetTypeIndex + ); + +VOID +cnmStaRecFree ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN BOOLEAN fgSyncToChip + ); + +VOID +cnmStaFreeAllStaByNetType ( + P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + BOOLEAN fgSyncToChip + ); + +P_STA_RECORD_T +cnmGetStaRecByIndex ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucIndex + ); + +P_STA_RECORD_T +cnmGetStaRecByAddress ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucNetTypeIndex, + IN UINT_8 aucPeerMACAddress[] + ); + +VOID +cnmStaRecResetStatus ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +VOID +cnmStaRecChangeState ( + IN P_ADAPTER_T prAdapter, + IN OUT P_STA_RECORD_T prStaRec, + IN UINT_8 ucNewState + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +__KAL_INLINE__ VOID +cnmMemDataTypeCheck ( + VOID + ) +{ +#if 0 + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,rLinkEntry) == 0); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,rLinkEntry) == OFFSET_OF(SW_RFB_T,rLinkEntry)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,pucBuffer) == OFFSET_OF(SW_RFB_T,pucBuffer)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucBufferSource) == + OFFSET_OF(SW_RFB_T,ucBufferSource)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,pucMacHeader) == + OFFSET_OF(SW_RFB_T,pucMacHeader)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucMacHeaderLength) == + OFFSET_OF(SW_RFB_T,ucMacHeaderLength)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,pucPayload) == + OFFSET_OF(SW_RFB_T,pucPayload)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,u2PayloadLength) == + OFFSET_OF(SW_RFB_T,u2PayloadLength)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,prStaRec) == + OFFSET_OF(SW_RFB_T,prStaRec)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucNetworkTypeIndex) == + OFFSET_OF(SW_RFB_T,ucNetworkTypeIndex)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucTID) == + OFFSET_OF(SW_RFB_T,ucTID)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,fgIs802_11Frame) == + OFFSET_OF(SW_RFB_T,fgIs802_11Frame)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucControlFlag) == + OFFSET_OF(SW_RFB_T,ucControlFlag)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,rArrivalTime) == + OFFSET_OF(SW_RFB_T,rArrivalTime)); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,ucTC) == + OFFSET_OF(SW_RFB_T,ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,eActivity[0]) == + OFFSET_OF(SW_RFB_T,eActivity[0])); + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,rActivityTime[0]) == + OFFSET_OF(SW_RFB_T,rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(MSDU_INFO_T,fgBufferInSource) == + OFFSET_OF(SW_RFB_T,fgBufferInSource)); +#endif + + + DATA_STRUC_INSPECTING_ASSERT( + OFFSET_OF(STA_RECORD_T,rLinkEntry) == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h new file mode 100755 index 000000000000..b3d2993f801a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h @@ -0,0 +1,206 @@ +/* +** $Id: @(#) +*/ + +/*! \file "cnm_scan.h" + \brief + +*/ + + + +/* +** $Log: cnm_scan.h $ + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * remove unused definitions. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function prototype of cnmScanInit() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_SCAN_H +#define _CNM_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define SCN_CHANNEL_DWELL_TIME_MIN_MSEC 12 +#define SCN_CHANNEL_DWELL_TIME_EXT_MSEC 98 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_FULL 3 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_FULL 1 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_PARTIAL 2 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_PARTIAL 1 + + +#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 /* Used by partial scan */ + +#define SCN_PARTIAL_SCAN_NUM 3 + +#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 + +#define MAXIMUM_OPERATION_CHANNEL_LIST 32 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* The type of Scan Source */ +typedef enum _ENUM_SCN_REQ_SOURCE_T { + SCN_REQ_SOURCE_HEM = 0, + SCN_REQ_SOURCE_NET_FSM, + SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ + SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ + SCN_REQ_SOURCE_NUM +} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; + +typedef enum _ENUM_SCAN_PROFILE_T { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +VOID +cnmScanInit ( + VOID + ); + +VOID +cnmScanRunEventScanRequest ( + IN P_MSG_HDR_T prMsgHdr + ); + +BOOLEAN +cnmScanRunEventScanAbort ( + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +cnmScanProfileSelection ( + VOID + ); + +VOID +cnmScanProcessStart ( + VOID + ); + +VOID +cnmScanProcessStop ( + VOID + ); + +VOID +cnmScanRunEventReqAISAbsDone ( + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +cnmScanRunEventCancelAISAbsDone ( + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +cnmScanPartialScanTimeout ( + UINT_32 u4Param + ); + +VOID +cnmScanRunEventScnFsmComplete ( + IN P_MSG_HDR_T prMsgHdr + ); +#endif + + + +#endif /* _CNM_SCAN_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h new file mode 100755 index 000000000000..b1ed2c6456ad --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h @@ -0,0 +1,274 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_timer.h#1 $ +*/ + +/*! \file cnm_timer.h + \brief Declaration of timer obj and related timer macro for setup time out + event. + + In this file we declare the timer object and provide several macro for + Protocol functional blocks to setup their own time out event. +*/ + + + +/* +** $Log: cnm_timer.h $ + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Return timer token back to COS when entering wait off state + * + * 01 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb + * + * 01 06 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix system time is 32KHz instead of 1ms + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the copy time function + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix LINT warnning + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_TIMER_H +#define _CNM_TIMER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#undef MSEC_PER_SEC +#define MSEC_PER_SEC 1000 +#undef USEC_PER_MSEC +#define USEC_PER_MSEC 1000 +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + + +#define MGMT_MAX_TIMEOUT_INTERVAL ((UINT_32)0x7fffffff) + +#define WAKE_LOCK_MAX_TIME 5 /* Unit: sec */ + +/* If WAKE_LOCK_MAX_TIME is too large, the whole system may always keep awake + * because of periodic timer of OBSS scanning + */ +#if (WAKE_LOCK_MAX_TIME >= OBSS_SCAN_MIN_INTERVAL) + #error WAKE_LOCK_MAX_TIME is too large +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef VOID (*PFN_MGMT_TIMEOUT_FUNC)(P_ADAPTER_T, UINT_32); + +typedef struct _TIMER_T { + LINK_ENTRY_T rLinkEntry; + OS_SYSTIME rExpiredSysTime; + UINT_16 u2Minutes; + UINT_16 u2Reserved; + UINT_32 u4Data; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; +} TIMER_T, *P_TIMER_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Check if time "a" is before time "b" */ +/* In 32-bit variable, 0x00000001~0x7fffffff -> positive number, + * 0x80000000~0xffffffff -> negative number + */ +#define TIME_BEFORE_64bit(a,b) (a < b) + +#define TIME_BEFORE(a,b) ((UINT_32)((UINT_32)(a) - (UINT_32)(b)) > 0x7fffffff) + +/* #define TIME_BEFORE(a,b) ((INT_32)((INT_32)(b) - (INT_32)(a)) > 0) + * may cause UNexpect result between Free build and Check build for WinCE + */ + +#define TIME_AFTER(a,b) TIME_BEFORE(b,a) + +#define SYSTIME_TO_SEC(_systime) ((_systime) / KAL_HZ) +#define SEC_TO_SYSTIME(_sec) ((_sec) * KAL_HZ) + + +/* The macros to convert second & millisecond */ +#define MSEC_TO_SEC(_msec) ((_msec) / MSEC_PER_SEC) +#define SEC_TO_MSEC(_sec) ((UINT_32)(_sec) * MSEC_PER_SEC) + + +/* The macros to convert millisecond & microsecond */ +#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_USEC(_msec) ((UINT_32)(_msec) * USEC_PER_MSEC) + + +/* The macros to convert TU & microsecond, TU & millisecond */ +#define TU_TO_USEC(_tu) ((_tu) * USEC_PER_TU) +#define TU_TO_MSEC(_tu) USEC_TO_MSEC( TU_TO_USEC(_tu) ) + + +/* The macros to convert TU & & OS system time, round up by 0.5 */ +#define TU_TO_SYSTIME(_tu) MSEC_TO_SYSTIME( TU_TO_MSEC(_tu) ) +#define SYSTIME_TO_TU(_systime) \ + ((SYSTIME_TO_USEC(_systime) + ((USEC_PER_TU / 2) - 1)) / USEC_PER_TU) + + +/* The macros to convert OS system time & microsecond */ +#define SYSTIME_TO_USEC(_systime) (SYSTIME_TO_MSEC(_systime) * USEC_PER_MSEC) + + +/* The macro to get the current OS system time */ +#define GET_CURRENT_SYSTIME(_systime_p) {*(_systime_p) = kalGetTimeTick();} + +/* The macro to copy the system time */ +#define COPY_SYSTIME(_destTime, _srcTime) (_destTime) = (_srcTime) + +/* The macro to get the system time difference between t1 and t2 (t1 - t2) */ +/* #define GET_SYSTIME_DIFFERENCE(_time1, _time2, _diffTime) \ + (_diffTime) = (_time1) - (_time2) */ + +/* The macro to check for the expiration, if TRUE means _currentTime >= _expirationTime */ +#define CHECK_FOR_EXPIRATION(_currentTime, _expirationTime) \ + ( ((UINT_32)(_currentTime) - (UINT_32)(_expirationTime)) <= 0x7fffffffUL) + +/* The macro to check for the timeout */ +#define CHECK_FOR_TIMEOUT(_currentTime, _timeoutStartingTime, _timeout) \ + CHECK_FOR_EXPIRATION((_currentTime), ((_timeoutStartingTime) + (_timeout))) + +/* The macro to set the expiration time with a specified timeout *//* Watch out for round up.*/ +#define SET_EXPIRATION_TIME(_expirationTime, _timeout) \ + { \ + GET_CURRENT_SYSTIME(&(_expirationTime)); \ + (_expirationTime) += (OS_SYSTIME)(_timeout); \ + } + +#define timerRenewTimer(adapter,tmr,interval) \ + timerStartTimer(adapter,tmr,interval,(tmr)->function,(tmr)->data) + +#define MGMT_INIT_TIMER(_adapter_p, _timer, _callbackFunc) \ + timerInitTimer(_adapter_p, &(_timer), (UINT_32)(_callbackFunc)) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +cnmTimerInitialize ( + IN P_ADAPTER_T prAdapter + ); + +VOID +cnmTimerDestroy ( + IN P_ADAPTER_T prAdapter + ); + +VOID +cnmTimerInitTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN UINT_32 u4Data + ); + +VOID +cnmTimerStopTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer + ); + +VOID +cnmTimerStartTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN UINT_32 u4TimeoutMs + ); + +VOID +cnmTimerDoTimeOutCheck ( + IN P_ADAPTER_T prAdapter + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +__KAL_INLINE__ +INT_32 +timerPendingTimer ( + IN P_TIMER_T prTimer + ) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +#endif /* _CNM_TIMER_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h new file mode 100755 index 000000000000..c86099c810e1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h @@ -0,0 +1,444 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/hem_mbox.h#2 $ +*/ + +/*! \file hem_mbox.h + \brief + +*/ + + + +/* +** $Log: hem_mbox.h $ +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 07 2011 yuche.tsai + * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response.[WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add invitation support. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 09 16 2010 cm.chang + * NULL + * Remove unused message ID + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some message ID for P2P FSM under provisioning phase. + * + * 08 11 2010 yuche.tsai + * NULL + * Add Message Event ID for P2P Module. + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 04 2010 cp.wu + * NULL + * remove unused mailbox message definitions. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * message table should not be commented out by compilation option without modifying header file + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_QOS_ACTION_FRAME + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_BA_ACTION_FRAME + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Develop partial DPD code + * + * 02 11 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added MID_RXM_MQM_QOS_ACTION_FRAME for RXM to indicate QoS Action frames to MQM + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename the parameter of mboxDummy() + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added MID_RXM_MQM_BA_ACTION_FRAME + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove Dummy MSG ID + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add JOIN REQ related MSG ID + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add AIS ABORT MSG ID + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add SCN MSG IDs + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _HEM_MBOX_H +#define _HEM_MBOX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Message IDs */ +typedef enum _ENUM_MSG_ID_T { + MID_MNY_CNM_CH_REQ, /* MANY notify CNM to obtain channel privilege */ + MID_MNY_CNM_CH_ABORT, /* MANY notify CNM to abort/release channel privilege */ + + MID_CNM_AIS_CH_GRANT, /* CNM notify AIS for indicating channel granted */ + MID_CNM_P2P_CH_GRANT, /* CNM notify P2P for indicating channel granted */ + MID_CNM_BOW_CH_GRANT, /* CNM notify BOW for indicating channel granted */ + + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_AIS_SCN_SCAN_REQ, /* AIS notify SCN for starting scan */ + MID_AIS_SCN_SCAN_REQ_V2, /* AIS notify SCN for starting scan with multiple SSID support */ + MID_AIS_SCN_SCAN_CANCEL, /* AIS notify SCN for cancelling scan */ + MID_P2P_SCN_SCAN_REQ, /* P2P notify SCN for starting scan */ + MID_P2P_SCN_SCAN_REQ_V2, /* P2P notify SCN for starting scan with multiple SSID support */ + MID_P2P_SCN_SCAN_CANCEL, /* P2P notify SCN for cancelling scan */ + MID_BOW_SCN_SCAN_REQ, /* BOW notify SCN for starting scan */ + MID_BOW_SCN_SCAN_REQ_V2, /* BOW notify SCN for starting scan with multiple SSID support */ + MID_BOW_SCN_SCAN_CANCEL, /* BOW notify SCN for cancelling scan */ + MID_RLM_SCN_SCAN_REQ, /* RLM notify SCN for starting scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_REQ_V2, /* RLM notify SCN for starting scan (OBSS-SCAN) with multiple SSID support */ + MID_RLM_SCN_SCAN_CANCEL, /* RLM notify SCN for cancelling scan (OBSS-SCAN)*/ + MID_SCN_AIS_SCAN_DONE, /* SCN notify AIS for scan completion */ + MID_SCN_P2P_SCAN_DONE, /* SCN notify P2P for scan completion */ + MID_SCN_BOW_SCAN_DONE, /* SCN notify BOW for scan completion */ + MID_SCN_RLM_SCAN_DONE, /* SCN notify RLM for scan completion (OBSS-SCAN) */ + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_OID_AIS_FSM_JOIN_REQ, /* OID/IOCTL notify AIS for join */ + MID_OID_AIS_FSM_ABORT, /* OID/IOCTL notify AIS for abort */ + MID_AIS_SAA_FSM_START, /* AIS notify SAA for Starting authentication/association fsm */ + MID_AIS_SAA_FSM_ABORT, /* AIS notify SAA for Aborting authentication/association fsm */ + MID_SAA_AIS_JOIN_COMPLETE, /* SAA notify AIS for indicating join complete */ + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_BOW_SAA_FSM_START, /* BOW notify SAA for Starting authentication/association fsm */ + MID_BOW_SAA_FSM_ABORT, /* BOW notify SAA for Aborting authentication/association fsm */ + MID_SAA_BOW_JOIN_COMPLETE, /* SAA notify BOW for indicating join complete */ +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*--------------------------------------------------*/ + /* P2P Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_P2P_SAA_FSM_START, /* P2P notify SAA for Starting authentication/association fsm */ + MID_P2P_SAA_FSM_ABORT, /* P2P notify SAA for Aborting authentication/association fsm */ + MID_SAA_P2P_JOIN_COMPLETE, /* SAA notify P2P for indicating join complete */ + + MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ + MID_MNY_P2P_DEVICE_DISCOVERY, /* Start device discovery. */ + MID_MNY_P2P_CONNECTION_REQ, /* Connection request. */ + MID_MNY_P2P_CONNECTION_ABORT, /* Abort connection request, P2P FSM return to IDLE. */ + MID_MNY_P2P_BEACON_UPDATE, + MID_MNY_P2P_STOP_AP, + MID_MNY_P2P_CHNL_REQ, + MID_MNY_P2P_CHNL_ABORT, + MID_MNY_P2P_MGMT_TX, + MID_MNY_P2P_GROUP_DISSOLVE, + MID_MNY_P2P_MGMT_FRAME_REGISTER, + MID_MNY_P2P_NET_DEV_REGISTER, + MID_MNY_P2P_START_AP, + MID_MNY_P2P_MGMT_FRAME_UPDATE, +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif +#endif + +#if CFG_SUPPORT_ADHOC + MID_SCN_AIS_FOUND_IBSS, /* SCN notify AIS that an IBSS Peer has been found and can merge into */ +#endif /* CFG_SUPPORT_ADHOC */ + + MID_SAA_AIS_FSM_ABORT, /* SAA notify AIS for indicating deauthentication/disassociation */ + + MID_TOTAL_NUM +} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; + +/* Message header of inter-components */ +struct _MSG_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_MSG_ID_T eMsgId; +}; + +typedef VOID (*PFN_MSG_HNDL_FUNC)(P_ADAPTER_T, P_MSG_HDR_T); + +typedef struct _MSG_HNDL_ENTRY { + ENUM_MSG_ID_T eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; + +typedef enum _EUNM_MSG_SEND_METHOD_T { + MSG_SEND_METHOD_BUF = 0, /* Message is put in the queue and will be + executed when mailbox is checked. */ + MSG_SEND_METHOD_UNBUF /* The handler function is called immediately + in the same context of the sender */ +} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; + + +typedef enum _ENUM_MBOX_ID_T { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; + +/* Define Mailbox structure */ +typedef struct _MBOX_T { + LINK_T rLinkHead; +} MBOX_T, *P_MBOX_T; + +typedef struct _MSG_SAA_FSM_START_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; + +typedef struct _MSG_SAA_FSM_COMP_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + WLAN_STATUS rJoinStatus; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prSwRfb; +} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; + +typedef struct _MSG_SAA_FSM_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; + +typedef struct _MSG_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; +} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; + + + +/* specific message data types */ +typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; +typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; +typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +mboxSetup ( + IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId + ); + + +VOID +mboxSendMsg ( + IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, + IN P_MSG_HDR_T prMsg, + IN EUNM_MSG_SEND_METHOD_T eMethod + ); + +VOID +mboxRcvAllMsg ( + IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId + ); + +VOID +mboxInitialize ( + IN P_ADAPTER_T prAdapter + ); + +VOID +mboxDestroy ( + IN P_ADAPTER_T prAdapter + ); + +VOID +mboxDummy ( + IN P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HEM_MBOX_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h new file mode 100755 index 000000000000..febcfb5fc40c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h @@ -0,0 +1,157 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/mib.h#1 $ +*/ + +/*! \file mib.h + \brief This file contains the IEEE 802.11 family related MIB definition + for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: mib.h $ + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _MIB_H +#define _MIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ +typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ +} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ +typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY +{ + UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ +} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ +typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY +{ + UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ +} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +typedef struct _IEEE_802_11_MIB_T { + /* dot11PrivacyTable (dot11smt 5) */ + UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + BOOLEAN dot11TranmitKeyAvailable; + UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 //SUPPORT_WAPI + BOOLEAN fgWapiKeyInstalled; + PARAM_WPI_KEY_T rWapiPairwiseKey[2]; + BOOLEAN fgPairwiseKeyUsed[2]; + UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + PARAM_WPI_KEY_T rWapiGroupKey[2]; + BOOLEAN fgGroupKeyUsed[2]; +#endif +} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +typedef const struct _NON_HT_PHY_ATTRIBUTE_T { + UINT_16 u2SupportedRateSet; + + BOOLEAN fgIsShortPreambleOptionImplemented; + + BOOLEAN fgIsShortSlotTimeOptionImplemented; + +} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; + +typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { + + ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; + + UINT_16 u2BSSBasicRateSet; + +} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; + +typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; +extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; +extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MIB_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h new file mode 100755 index 000000000000..270d1d63c7fb --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h @@ -0,0 +1,64 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_assoc.h#1 $ +*/ + +/*! \file p2p_assoc.h + \brief This file contains the Wi-Fi Direct ASSOC REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + + +#ifndef _P2P_ASSOC_H +#define _P2P_ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +PUINT_8 +p2pBuildReAssocReqFrameCommonIEs ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucBuffer + ); + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h new file mode 100755 index 000000000000..a609476fff7d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h @@ -0,0 +1,65 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_bss.h#2 $ +*/ + +/*! \file "p2p_bss.h" + \brief In this file we define the function prototype used in p2p BSS/IBSS. + + The file contains the function declarations and defines for used in BSS/IBSS. +*/ + + + + + +#ifndef _P2P_BSS_H +#define _P2P_BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +UINT_32 +p2pGetTxProbRspIeTableSize( + VOID + ); + +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h new file mode 100755 index 000000000000..9cd9b36d2936 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h @@ -0,0 +1,2778 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_fsm.h#23 $ +*/ + +/*! \file p2p_fsm.h + \brief Declaration of functions and finite state machine for P2P Module. + + Declaration of functions and finite state machine for P2P Module. +*/ + + + +/* +** $Log: p2p_fsm.h $ +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 14 2012 yuche.tsai +** NULL +** Fix compile error. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 18 2012 yuche.tsai + * NULL + * add one file. + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve class 3 error issue under AP mode. + * + * data frame may TX before Assoc Response TX. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix default device name issue. + * + * 11 09 2011 yuche.tsai + * [WCXRP00001093] [Need Patch][Volunteer Patch] Service Discovery 2.0 state transition issue. + * Fix SD2.0 issue which may cause KE. (Monkey test) + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channle Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 09 01 2011 yuche.tsai + * NULL + * Fix channel stay interval. + * Sync channel stay interval & channel request interval under AP mode.. + * + * 08 30 2011 yuche.tsai + * [WCXRP00000953] [Volunteer Patch][Driver] Hot Spot Channel ASSERT issue. + * Fix hot spot FW assert issue when under concurrent case. (DBG enable only) + * + * 08 16 2011 cp.wu + * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence + * auto channel decision for 2.4GHz hot spot mode + * + * 08 16 2011 yuche.tsai + * NULL + * Fix scan policy for Active LISTEN scan. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Support TX Deauth Issue. + * + * 07 26 2011 yuche.tsai + * [WCXRP00000875] [Volunteer Patch][WiFi Direct][Driver] MT6620 IOT issue with realtek test bed solution. + * Turn off persistent group support for V2.0 release. + * + * 07 18 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Fix compile error. + * + * 07 18 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Fix MT6620 WiFi Direct IOT Issue with BCM solution. + * + * 07 11 2011 yuche.tsai + * [WCXRP00000845] [Volunteer Patch][WiFi Direct] WiFi Direct Device Connection Robustness + * Enhance Connection Robustness. + * + * 07 08 2011 yuche.tsai + * [WCXRP00000841] [Volunteer Patch][WiFi Direct] Group Owner Setting. + * Update GO configure parameter. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Disable enhancement II for debugging. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Refine compile flag. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix connection indication twice issue. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 05 04 2011 yuche.tsai + * NULL + * Support partial persistent group function. + * + * 04 20 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove CFG_WIFI_DIRECT_MOVED. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 22 2011 yuche.tsai + * NULL + * 1.Shorten the LISTEN interval. + * 2. Fix IF address issue when we are GO + * 3. Fix LISTEN channel issue. + * + * 03 21 2011 yuche.tsai + * NULL + * Change P2P Connection Request Flow. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 07 2011 yuche.tsai + * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the ioctl setting that index not map to spec defined config method. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC IE BE format issue. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 11 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add two function prototype. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Support Disassoc & Deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. + +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. + +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 25 2011 terry.wu + * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter + * Add a new module parameter to indicate current runnig mode, P2P or AP. + * + * 01 19 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Null NOA attribute setting when no related parameters. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify some behavior of AP mode. + * + * 12 22 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Compile Error. + * + * 12 15 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Refine Connection Flow. + * + * 12 08 2010 yuche.tsai + * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. + * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client by checking the P2P IE in assoc req frame. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation & Provision Discovery. + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 30 2010 yuche.tsai + * NULL + * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ + * + * 11 29 2010 yuche.tsai + * NULL + * Update P2P related function for INVITATION & PROVISION DISCOVERY. + * + * 11 26 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Update P2P PS for NOA function. + * + * 11 25 2010 yuche.tsai + * NULL + * Update Code for Invitation Related Function. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at WinXP. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 26 2010 yuche.tsai + * NULL + * Add connection abort message event prototype. + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 16 2010 yuche.tsai + * NULL + * Fix P2P Intended Interface Address Bug. + * Extend GO Nego Timeout Time. + * + * 08 16 2010 yuche.tsai + * NULL + * Extend Listen Interval default value & remove deprecated variable. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Add function prototype for join complete. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some function proto type for P2P FSM under provisioning phase.. + * + * 08 11 2010 yuche.tsai + * NULL + * Change P2P data structure for supporting + * 1. P2P Device discovery. + * 2. P2P Group Negotiation. + * 3. P2P JOIN + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Update P2P FSM header file. + * + * 07 23 2010 cp.wu + * + * P2P/RSN/WAPI IEs need to be declared with compact structure. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Update P2P FSM header file. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix some P2P function prototype. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename CFG flag for P2P + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify parameter of p2pStartGO + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add Wi-Fi Direct SSID and P2P GO Test Mode + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CID52_53_54 0 + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_P2P_STATE_T { + P2P_STATE_IDLE = 0, + P2P_STATE_SCAN, + P2P_STATE_AP_CHANNEL_DETECT, + P2P_STATE_REQING_CHANNEL, + P2P_STATE_CHNL_ON_HAND, /* Requesting Channel to Send Specific Frame. */ + P2P_STATE_GC_JOIN, /* Sending Specific Frame. May extending channel by other event. */ + P2P_STATE_NUM +} ENUM_P2P_STATE_T, *P_ENUM_P2P_STATE_T; + + +typedef enum _ENUM_CHANNEL_REQ_TYPE_T { + CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL, + CHANNEL_REQ_TYPE_GC_JOIN_REQ, + CHANNEL_REQ_TYPE_GO_START_BSS +} +ENUM_CHANNEL_REQ_TYPE_T, *P_ENUM_CHANNEL_REQ_TYPE_T; + + +typedef enum _ENUM_BUFFER_TYPE_T { + ENUM_FRAME_TYPE_EXTRA_IE_BEACON, + ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP, + ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP, + ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE, + ENUM_FRAME_TYPE_BEACON_TEMPLATE, + ENUM_FRAME_IE_NUM +} ENUM_BUFFER_TYPE_T, *P_ENUM_BUFFER_TYPE_T; + +typedef enum _ENUM_HIDDEN_SSID_TYPE_T { + ENUM_HIDDEN_SSID_NONE, + ENUM_HIDDEN_SSID_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +} +ENUM_HIDDEN_SSID_TYPE_T, *P_ENUM_HIDDEN_SSID_TYPE_T; + +typedef struct _P2P_SSID_STRUCT_T { + UINT_8 aucSsid[32]; + UINT_8 ucSsidLen; +} P2P_SSID_STRUCT_T, *P_P2P_SSID_STRUCT_T; + +typedef struct _P2P_STATION_INFO_T { + UINT_32 u4InactiveTime; + UINT_32 u4RxBytes; // TODO: + UINT_32 u4TxBytes; // TODO: + UINT_32 u4RxPackets; // TODO: + UINT_32 u4TxPackets; // TODO: + // TODO: Add more for requirement. +} +P2P_STATION_INFO_T, *P_P2P_STATION_INFO_T; + + +typedef struct _AP_CRYPTO_SETTINGS_T { + UINT_32 u4WpaVersion; + UINT_32 u4CipherGroup; + INT_32 i4NumOfCiphers; + UINT_32 aucCiphersPairwise[5]; + INT_32 i4NumOfAkmSuites; + UINT_32 aucAkmSuites[2]; + BOOLEAN fgIsControlPort; + UINT_16 u2ControlPortBE; + BOOLEAN fgIsControlPortEncrypt; +} AP_CRYPTO_SETTINGS_T, *P_AP_CRYPTO_SETTINGS_T; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ +typedef struct _P2P_CHNL_REQ_INFO_T { + BOOLEAN fgIsChannelRequested; + UINT_8 ucSeqNumOfChReq; + UINT_64 u8Cookie; + UINT_8 ucReqChnlNum; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eChnlSco; + UINT_32 u4MaxInterval; + ENUM_CHANNEL_REQ_TYPE_T eChannelReqType; + + UINT_8 ucOriChnlNum; + ENUM_BAND_T eOriBand; + ENUM_CHNL_EXT_T eOriChnlSco; +} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; + +typedef struct _P2P_SCAN_REQ_INFO_T { + ENUM_SCAN_TYPE_T eScanType; + ENUM_SCAN_CHANNEL eChannelSet; + UINT_16 u2PassiveDewellTime; + UINT_8 ucSeqNumOfScnMsg; + BOOLEAN fgIsAbort; + BOOLEAN fgIsScanRequest; + UINT_8 ucNumChannelList; + RF_CHANNEL_INFO_T arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + P2P_SSID_STRUCT_T rSsidStruct; // Currently we can only take one SSID scan request +} +P2P_SCAN_REQ_INFO_T, *P_P2P_SCAN_REQ_INFO_T; + +typedef struct _P2P_CONNECTION_REQ_INFO_T { + + BOOLEAN fgIsConnRequest; + P2P_SSID_STRUCT_T rSsidStruct; + UINT_8 aucBssid[MAC_ADDR_LEN]; + /* For ASSOC Req. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_CONNECTION_REQ_INFO_T, *P_P2P_CONNECTION_REQ_INFO_T; + +typedef struct _P2P_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; + +typedef struct _P2P_BEACON_UPDATE_INFO_T { + PUINT_8 pucBcnHdr; + UINT_32 u4BcnHdrLen; + PUINT_8 pucBcnBody; + UINT_32 u4BcnBodyLen; +} +P2P_BEACON_UPDATE_INFO_T, *P_P2P_BEACON_UPDATE_INFO_T; + +typedef struct _P2P_PROBE_RSP_UPDATE_INFO_T { + P_MSDU_INFO_T prProbeRspMsduTemplate; +} P2P_PROBE_RSP_UPDATE_INFO_T, *P_P2P_PROBE_RSP_UPDATE_INFO_T; + +typedef struct _P2P_ASSOC_RSP_UPDATE_INFO_T { + PUINT_8 pucAssocRspExtIE; + UINT_16 u2AssocIELen; +} P2P_ASSOC_RSP_UPDATE_INFO_T, *P_P2P_ASSOC_RSP_UPDATE_INFO_T; + +typedef struct _P2P_JOIN_INFO_T { + UINT_32 ucSeqNumOfReqMsg; + UINT_8 ucAvailableAuthTypes; + P_STA_RECORD_T prTargetStaRec; + P2P_SSID_STRUCT_T rSsidStruct; + BOOLEAN fgIsJoinComplete; + /* For ASSOC Rsp. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} +P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; + +#if CFG_SUPPORT_WFD + +#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ +#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ +#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ +#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ + + + +struct _WFD_CFG_SETTINGS_T { + UINT_32 u4WfdCmdType; + UINT_8 ucWfdEnable; + UINT_8 ucWfdCoupleSinkStatus; + UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + UINT_8 ucWfdSigmaMode; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdControlPort; + UINT_16 u2WfdMaximumTp; + UINT_16 u2WfdExtendCap; + UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 aucWfdVideolp[4]; + UINT_8 aucWfdAudiolp[4]; + UINT_16 u2WfdVideoPort; + UINT_16 u2WfdAudioPort; + UINT_32 u4WfdFlag; + UINT_32 u4WfdPolicy; + UINT_32 u4WfdState; + UINT_8 aucWfdSessionInformationIE[24*8]; + UINT_16 u2WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_8 aucReverved2[56]; + /* Group 2 64 bytes */ + UINT_8 aucReverved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReverved4[64]; + +}; + +#endif + + + +struct _P2P_FSM_INFO_T { + /* State related. */ + ENUM_P2P_STATE_T ePreviousState; + ENUM_P2P_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Connection related. */ + P2P_CONNECTION_REQ_INFO_T rConnReqInfo; + + /* Mgmt tx related. */ + P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Beacon related. */ + P2P_BEACON_UPDATE_INFO_T rBcnContentInfo; + + /* Probe Response related. */ + P2P_PROBE_RSP_UPDATE_INFO_T rProbeRspContentInfo; + + /* Assoc Rsp related. */ + P2P_ASSOC_RSP_UPDATE_INFO_T rAssocRspContentInfo; + + /* GC Join related. */ + P2P_JOIN_INFO_T rJoinInfo; + + /* FSM Timer */ + TIMER_T rP2pFsmTimeoutTimer; + + + /* GC Target BSS. */ + P_BSS_DESC_T prTargetBss; + + /* GC Connection Request. */ + BOOLEAN fgIsConnectionRequested; + + BOOLEAN fgIsApMode; + + /* Channel grant interval. */ + UINT_32 u4GrantInterval; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; + + //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Prepare for use vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + /* Msg event queue. */ + LINK_T rMsgEventQueue; + +#if CFG_SUPPORT_WFD + WFD_CFG_SETTINGS_T rWfdConfigureSettings; +#endif + +}; + + +/*---------------- Messages -------------------*/ +typedef struct _MSG_P2P_SCAN_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P_P2P_SSID_STRUCT_T prSSID; + INT_32 i4SsidNum; + UINT_32 u4NumChannel; + PUINT_8 pucIEBuf; + UINT_32 u4IELen; + BOOLEAN fgIsAbort; + RF_CHANNEL_INFO_T arChannelListInfo[1]; +} MSG_P2P_SCAN_REQUEST_T, *P_MSG_P2P_SCAN_REQUEST_T; + +typedef struct _MSG_P2P_CHNL_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; + UINT_32 u4Duration; + ENUM_CHNL_EXT_T eChnlSco; + RF_CHANNEL_INFO_T rChannelInfo; +} MSG_P2P_CHNL_REQUEST_T, *P_MSG_P2P_CHNL_REQUEST_T; + +typedef struct _MSG_P2P_CHNL_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_P2P_CHNL_ABORT_T, *P_MSG_P2P_CHNL_ABORT_T; + + +typedef struct _MSG_P2P_CONNECTION_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P2P_SSID_STRUCT_T rSsid; + UINT_8 aucBssid[MAC_ADDR_LEN]; + ENUM_CHNL_EXT_T eChnlSco; + RF_CHANNEL_INFO_T rChannelInfo; + UINT_32 u4IELen; + UINT_8 aucIEBuf[1]; + // TODO: Auth Type, OPEN, SHARED, FT, EAP... +} MSG_P2P_CONNECTION_REQUEST_T, *P_MSG_P2P_CONNECTION_REQUEST_T; + + +typedef struct _MSG_P2P_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member. */ + UINT_8 aucTargetID[MAC_ADDR_LEN]; + UINT_16 u2ReasonCode; + BOOLEAN fgSendDeauth; +} MSG_P2P_CONNECTION_ABORT_T, *P_MSG_P2P_CONNECTION_ABORT_T; + +typedef struct _MSG_P2P_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_P2P_MGMT_TX_REQUEST_T, *P_MSG_P2P_MGMT_TX_REQUEST_T; + +typedef struct _MSG_P2P_START_AP_T { + MSG_HDR_T rMsgHdr; + UINT_32 u4DtimPeriod; + UINT_32 u4BcnInterval; + UINT_8 aucSsid[32]; + UINT_16 u2SsidLen; + UINT_8 ucHiddenSsidType; + BOOLEAN fgIsPrivacy; + AP_CRYPTO_SETTINGS_T rEncryptionSettings; + INT_32 i4InactiveTimeout; +} +MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_T; + + +typedef struct _MSG_P2P_BEACON_UPDATE_T { + MSG_HDR_T rMsgHdr; + UINT_32 u4BcnHdrLen; + UINT_32 u4BcnBodyLen; + PUINT_8 pucBcnHdr; + PUINT_8 pucBcnBody; + UINT_8 aucBuffer[1]; /* Header & Body are put here. */ +} +MSG_P2P_BEACON_UPDATE_T, *P_MSG_P2P_BEACON_UPDATE_T; + +typedef struct _MSG_P2P_MGMT_FRAME_UPDATE_T { + MSG_HDR_T rMsgHdr; + ENUM_BUFFER_TYPE_T eBufferType; + UINT_32 u4BufferLen; + UINT_8 aucBuffer[1]; +} MSG_P2P_MGMT_FRAME_UPDATE_T, *P_MSG_P2P_MGMT_FRAME_UPDATE_T; + + +typedef struct _MSG_P2P_SWITCH_OP_MODE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_OP_MODE_T eOpMode; +} MSG_P2P_SWITCH_OP_MODE_T, *P_MSG_P2P_SWITCH_OP_MODE_T; + +typedef struct _MSG_P2P_MGMT_FRAME_REGISTER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_16 u2FrameType; + BOOLEAN fgIsRegister; +} +MSG_P2P_MGMT_FRAME_REGISTER_T, *P_MSG_P2P_MGMT_FRAME_REGISTER_T; + +typedef struct _MSG_P2P_NETDEV_REGISTER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsEnable; + UINT_8 ucMode; +} MSG_P2P_NETDEV_REGISTER_T, *P_MSG_P2P_NETDEV_REGISTER_T; + +#if CFG_SUPPORT_WFD +typedef struct _MSG_WFD_CONFIG_SETTINGS_CHANGED_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings; +} MSG_WFD_CONFIG_SETTINGS_CHANGED_T, *P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T; +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +p2pFsmStateTransition( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ); + + + +VOID +p2pFsmRunEventAbort( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + + +VOID +p2pFsmRunEventScanRequest( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventMgmtFrameTx( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventStartAP( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventNetDeviceRegister( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventUpdateMgmtFrame( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventBeaconUpdate( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventStopAP( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventChannelRequest( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +VOID +p2pFsmRunEventChannelAbort( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +VOID +p2pFsmRunEventDissolve( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +VOID +p2pFsmRunEventSwitchOPMode( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +WLAN_STATUS +p2pFsmRunEventMgmtFrameTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + + +VOID +p2pFsmRunEventMgmtFrameRegister( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +#if CFG_SUPPORT_WFD +VOID +p2pFsmRunEventWfdSettingUpdate( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); +#endif + + +#if 0 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#endif + +//3 /* --------------- WFA P2P DEFAULT PARAMETERS --------------- */ +#define P2P_WILDCARD_SSID "DIRECT-" +#define P2P_WILDCARD_SSID_LEN 7 +#define P2P_GROUP_ID_LEN 9 + +#define P2P_DRIVER_VERSION 2 /* Update when needed. */ + +#define P2P_DEFAULT_DEV_NAME "Wireless Client" +#define P2P_DEFAULT_DEV_NAME_LEN 15 +#define P2P_DEFAULT_PRIMARY_CATEGORY_ID 10 +#define P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID 5 +#define P2P_DEFAULT_CONFIG_METHOD (WPS_ATTRI_CFG_METHOD_PUSH_BUTTON | WPS_ATTRI_CFG_METHOD_KEYPAD | WPS_ATTRI_CFG_METHOD_DISPLAY) +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#define P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT 0 /* NOTE(Kevin): Shall <= 16 */ +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT 13 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ + +#define P2P_MAXIMUM_CLIENT_COUNT 8 +#define P2P_MAXIMUM_NOA_COUNT 8 + + +#define P2P_MAXIMUM_ATTRIBUTE_LEN 251 + +#define P2P_CTWINDOW_DEFAULT 25 /* in TU=(1024usec) */ + +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 + +/* P2P 3.1.2.1.3 - Find Phase */ +#define P2P_MAX_DISCOVERABLE_INTERVAL 8 //3//3 +#define P2P_MIN_DISCOVERABLE_INTERVAL 5 // 1 + +#define P2P_LISTEN_SCAN_UNIT 100 // MS + +/* FSM Time Related constrain. */ +#define P2P_SERACH_STATE_PERIOD_MS 1000 // Deprecated. + +#define P2P_GO_CHANNEL_STAY_INTERVAL 1000 + +#define P2P_GO_NEGO_TIMEOUT_MS 500 +#define P2P_CONNECTION_TIMEOUT_SEC 120 + +#define P2P_INVITAION_TIMEOUT_MS 500 /* Timeout Wait Invitation Resonse. */ +#define P2P_PROVISION_DISCOVERY_TIMEOUT_MS 500 /* Timeout Wait Provision Discovery Resonse. */ + +//3 /* --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, aucP2PAttributes[0]) */ + +/* P2P 4.1.1 - General P2P Attribute */ +#define P2P_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ + +/* P2P 4.1.1 - P2P Attribute ID definitions */ +#define P2P_ATTRI_ID_STATUS 0 +#define P2P_ATTRI_ID_REASON_CODE 1 +#define P2P_ATTRI_ID_P2P_CAPABILITY 2 +#define P2P_ATTRI_ID_P2P_DEV_ID 3 +#define P2P_ATTRI_ID_GO_INTENT 4 +#define P2P_ATTRI_ID_CFG_TIMEOUT 5 +#define P2P_ATTRI_ID_LISTEN_CHANNEL 6 +#define P2P_ATTRI_ID_P2P_GROUP_BSSID 7 +#define P2P_ATTRI_ID_EXT_LISTEN_TIMING 8 +#define P2P_ATTRI_ID_INTENDED_P2P_IF_ADDR 9 +#define P2P_ATTRI_ID_P2P_MANAGEABILITY 10 +#define P2P_ATTRI_ID_CHANNEL_LIST 11 +#define P2P_ATTRI_ID_NOTICE_OF_ABSENCE 12 +#define P2P_ATTRI_ID_P2P_DEV_INFO 13 +#define P2P_ATTRI_ID_P2P_GROUP_INFO 14 +#define P2P_ATTRI_ID_P2P_GROUP_ID 15 +#define P2P_ATTRI_ID_P2P_INTERFACE 16 +#define P2P_ATTRI_ID_OPERATING_CHANNEL 17 +#define P2P_ATTRI_ID_INVITATION_FLAG 18 +#define P2P_ATTRI_ID_VENDOR_SPECIFIC 221 + +/* Maximum Length of P2P Attributes */ +#define P2P_ATTRI_MAX_LEN_STATUS 1 /* 0 */ +#define P2P_ATTRI_MAX_LEN_REASON_CODE 1 /* 1 */ +#define P2P_ATTRI_MAX_LEN_P2P_CAPABILITY 2 /* 2 */ +#define P2P_ATTRI_MAX_LEN_P2P_DEV_ID 6 /* 3 */ +#define P2P_ATTRI_MAX_LEN_GO_INTENT 1 /* 4 */ +#define P2P_ATTRI_MAX_LEN_CFG_TIMEOUT 2 /* 5 */ +#if CID52_53_54 + #define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#else + #define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#endif +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_BSSID 6 /* 7 */ +#define P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING 4 /* 8 */ +#define P2P_ATTRI_MAX_LEN_INTENDED_P2P_IF_ADDR 6 /* 9 */ +#define P2P_ATTRI_MAX_LEN_P2P_MANAGEABILITY 1 /* 10 */ +//#define P2P_ATTRI_MAX_LEN_CHANNEL_LIST 3 + (n* (2 + num_of_ch)) /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_LIST 3 /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_ENTRY 2 /* 11 */ + + +//#define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE 2 + (n* (13)) /* 12 */ +#define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE (2 + (P2P_MAXIMUM_NOA_COUNT*(13))) /* 12 */ + +#define P2P_ATTRI_MAX_LEN_P2P_DEV_INFO 17 + (8 * (8)) + 36 /* 13 */ +//#define P2P_ATTRI_MAX_LEN_P2P_GROUP_INFO n* (25 + (m* (8)) + 32) /* 14 */ +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_ID 38 /* 15 */ +#define P2P_ATTRI_MAX_LEN_P2P_INTERFACE 253 // 7 + 6* [0~41] /* 16 */ +#if CID52_53_54 + #define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#else + #define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#endif +#define P2P_ATTRI_MAX_LEN_INVITATION_FLAGS 1 /* 18 */ + +/* P2P 4.1.2 - P2P Status definitions */ +#define P2P_STATUS_SUCCESS 0 +#define P2P_STATUS_FAIL_INFO_IS_CURRENTLY_UNAVAILABLE 1 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 2 +#define P2P_STATUS_FAIL_LIMIT_REACHED 3 +#define P2P_STATUS_FAIL_INVALID_PARAM 4 +#define P2P_STATUS_FAIL_UNABLE_ACCOMMODATE_REQ 5 +#define P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR 6 +#define P2P_STATUS_FAIL_NO_COMMON_CHANNELS 7 +#define P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP 8 +#define P2P_STATUS_FAIL_SAME_INTENT_VALUE_15 9 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVISION_METHOD 10 +#define P2P_STATUS_FAIL_REJECTED_BY_USER 11 + + +/* P2P 4.1.3 - P2P Minor Reason Code definitions */ +#define P2P_REASON_SUCCESS 0 +#define P2P_REASON_DISASSOCIATED_DUE_CROSS_CONNECTION 1 +#define P2P_REASON_DISASSOCIATED_DUE_UNMANAGEABLE 2 +#define P2P_REASON_DISASSOCIATED_DUE_NO_P2P_COEXIST_PARAM 3 +#define P2P_REASON_DISASSOCIATED_DUE_MANAGEABLE 4 + + +/* P2P 4.1.4 - Device Capability Bitmap definitions */ +#define P2P_DEV_CAPABILITY_SERVICE_DISCOVERY BIT(0) +#define P2P_DEV_CAPABILITY_CLIENT_DISCOVERABILITY BIT(1) +#define P2P_DEV_CAPABILITY_CONCURRENT_OPERATION BIT(2) +#define P2P_DEV_CAPABILITY_P2P_INFRA_MANAGED BIT(3) +#define P2P_DEV_CAPABILITY_P2P_DEVICE_LIMIT BIT(4) +#define P2P_DEV_CAPABILITY_P2P_INVITATION_PROCEDURE BIT(5) + + +/* P2P 4.1.4 - Group Capability Bitmap definitions */ +#define P2P_GROUP_CAPABILITY_P2P_GROUP_OWNER BIT(0) +#define P2P_GROUP_CAPABILITY_PERSISTENT_P2P_GROUP BIT(1) +#define P2P_GROUP_CAPABILITY_P2P_GROUP_LIMIT BIT(2) +#define P2P_GROUP_CAPABILITY_INTRA_BSS_DISTRIBUTION BIT(3) +#define P2P_GROUP_CAPABILITY_CROSS_CONNECTION BIT(4) +#define P2P_GROUP_CAPABILITY_PERSISTENT_RECONNECT BIT(5) +#define P2P_GROUP_CAPABILITY_GROUP_FORMATION BIT(6) + +/* P2P 4.1.6 - GO Intent field definitions */ +#define P2P_GO_INTENT_TIE_BREAKER_FIELD BIT(0) +#define P2P_GO_INTENT_VALUE_MASK BITS(1,7) +#define P2P_GO_INTENT_VALUE_OFFSET 1 + +/* P2P 4.1.12 - Manageability Bitmap definitions */ +#define P2P_DEVICE_MANAGEMENT BIT(0) + +/* P2P 4.1.14 - CTWindow and OppPS Parameters definitions */ +#define P2P_CTW_OPPPS_PARAM_OPPPS_FIELD BIT(7) +#define P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK BITS(0,6) + + +#define ELEM_MAX_LEN_P2P_FOR_PROBE_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_ID) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL)) + +#define ELEM_MAX_LEN_P2P_FOR_ASSOC_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_INFO)) + + +/* P2P 4.1.16 - P2P Client Infor Descriptor */ +#define P2P_CLIENT_INFO_DESC_HDR_LEN 1 /* Length(1 octets) */ + +/* P2P 4.1.20 - P2P Invitation Flags Attribute*/ +#define P2P_INVITATION_FLAGS_INVITATION_TYPE BIT(0) +#define P2P_INVITATION_TYPE_INVITATION 0 +#define P2P_INVITATION_TYPE_REINVOKE 1 +//3 /* --------------- WPS Data Element Definitions --------------- */ +/* P2P 4.2.2 - General WSC Attribute */ +#define WSC_ATTRI_HDR_LEN 4 /* ID(2 octet) + Length(2 octets) */ +#define WSC_ATTRI_MAX_LEN_VERSION 1 +#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 +#define WSC_ATTRI_LEN_CONFIG_METHOD 2 + +/* WPS 11 - Data Element Definitions */ +#define WPS_ATTRI_ID_VERSION 0x104A +#define WPS_ATTRI_ID_CONFIGURATION_METHODS 0x1008 +#define WPS_ATTRI_ID_DEVICE_PASSWORD 0x1012 +#define WPS_ATTRI_ID_DEVICE_NAME 0x1011 +#define WPS_ATTRI_ID_PRI_DEVICE_TYPE 0x1054 +#define WPS_ATTRI_ID_SEC_DEVICE_TYPE 0x1055 + +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ + +#define WPS_ATTRI_CFG_METHOD_USBA BIT(0) +#define WPS_ATTRI_CFG_METHOD_ETHERNET BIT(1) +#define WPS_ATTRI_CFG_METHOD_LABEL BIT(2) +#define WPS_ATTRI_CFG_METHOD_DISPLAY BIT(3) +#define WPS_ATTRI_CFG_METHOD_EXT_NFC BIT(4) +#define WPS_ATTRI_CFG_METHOD_INT_NFC BIT(5) +#define WPS_ATTRI_CFG_METHOD_NFC_IF BIT(6) +#define WPS_ATTRI_CFG_METHOD_PUSH_BUTTON BIT(7) +#define WPS_ATTRI_CFG_METHOD_KEYPAD BIT(8) + + +#define P2P_FLAGS_PROVISION_COMPLETE 0x00000001 +#define P2P_FLAGS_PROVISION_DISCOVERY_COMPLETE 0x00000002 +#define P2P_FLAGS_PROVISION_DISCOVERY_WAIT_RESPONSE 0x00000004 +#define P2P_FLAGS_PROVISION_DISCOVERY_RESPONSE_WAIT 0x00000008 +#define P2P_FLAGS_MASK_PROVISION 0x00000017 +#define P2P_FLAGS_MASK_PROVISION_COMPLETE 0x00000015 +#define P2P_FLAGS_PROVISION_DISCOVERY_INDICATED 0x00000010 +#define P2P_FLAGS_INVITATION_TOBE_GO 0x00000100 +#define P2P_FLAGS_INVITATION_TOBE_GC 0x00000200 +#define P2P_FLAGS_INVITATION_SUCCESS 0x00000400 +#define P2P_FLAGS_INVITATION_WAITING_TARGET 0x00000800 +#define P2P_FLAGS_MASK_INVITATION 0x00000F00 +#define P2P_FLAGS_FORMATION_ON_GOING 0x00010000 +#define P2P_FLAGS_FORMATION_LOCAL_PWID_RDY 0x00020000 +#define P2P_FLAGS_FORMATION_TARGET_PWID_RDY 0x00040000 +#define P2P_FLAGS_FORMATION_COMPLETE 0x00080000 +#define P2P_FLAGS_MASK_FORMATION 0x000F0000 +#define P2P_FLAGS_DEVICE_DISCOVER_REQ 0x00100000 +#define P2P_FLAGS_DEVICE_DISCOVER_DONE 0x00200000 +#define P2P_FLAGS_DEVICE_INVITATION_WAIT 0x00400000 +#define P2P_FLAGS_DEVICE_SERVICE_DISCOVER_WAIT 0x00800000 +#define P2P_FLAGS_MASK_DEVICE_DISCOVER 0x00F00000 + +#define P2P_FLAGS_DEVICE_FORMATION_REQUEST 0x01000000 + + +/* MACRO for flag operation */ +#define SET_FLAGS(_FlagsVar, _BitsToSet) \ + (_FlagsVar) = ((_FlagsVar) | (_BitsToSet)) + +#define TEST_FLAGS(_FlagsVar, _BitsToCheck) \ + (((_FlagsVar) & (_BitsToCheck)) == (_BitsToCheck)) + +#define CLEAR_FLAGS(_FlagsVar, _BitsToClear) \ + (_FlagsVar) &= ~(_BitsToClear) + + + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_I 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_II 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_III 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_IV 0 + +#define CFG_DISABLE_DELAY_PROVISION_DISCOVERY 0 + +#define CFG_CONNECTION_POLICY_2_0 0 + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005 +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +//3 /* --------------- WFA P2P IE and Attributes --------------- */ + +/* P2P 4.1.1 - P2P Information Element */ +typedef struct _IE_P2P_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucP2PAttributes[1]; /* P2P Attributes */ +} __KAL_ATTRIB_PACKED__ IE_P2P_T, *P_IE_P2P_T; + +/* P2P 4.1.1 - General P2P Attribute */ +typedef struct _P2P_ATTRIBUTE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRIBUTE_T, ATTRIBUTE_HDR_T, *P_P2P_ATTRIBUTE_T, *P_ATTRIBUTE_HDR_T; + + +/* P2P 4.1.2 - P2P Status Attribute */ +typedef struct _P2P_ATTRI_STATUS_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucStatusCode; /* Status Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_STATUS_T, *P_P2P_ATTRI_STATUS_T; + + +/* P2P 4.1.3 - P2P Minor Reason Code Attribute */ +typedef struct _P2P_ATTRI_REASON_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucMinorReasonCode; /* Minor Reason Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_REASON_T, *P_P2P_ATTRI_REASON_T; + + +/* P2P 4.1.4 - P2P Capability Attribute */ +typedef struct _P2P_ATTRI_CAPABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_8 ucGroupCap; /* Group Capability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CAPABILITY_T, *P_P2P_ATTRI_CAPABILITY_T; + + +/* P2P 4.1.5 - P2P Device ID Attribute */ +typedef struct _P2P_ATTRI_DEV_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_ID_T, *P_P2P_ATTRI_DEV_ID_T; + + +/* P2P 4.1.6 - Group Owner Intent Attribute */ +typedef struct _P2P_ATTRI_GO_INTENT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOIntent; /* Group Owner Intent */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GO_INTENT_T, *P_P2P_ATTRI_GO_INTENT_T; + + +/* P2P 4.1.7 - Configuration Timeout Attribute */ +typedef struct _P2P_ATTRI_CFG_TIMEOUT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOCfgTimeout; /* GO Configuration Timeout */ + UINT_8 ucClientCfgTimeout; /* Client Configuration Timeout */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CFG_TIMEOUT_T, *P_P2P_ATTRI_CFG_TIMEOUT_T; + + +/* P2P 4.1.8 - Listen Channel Attribute */ +typedef struct _P2P_ATTRI_LISTEN_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_LISTEN_CHANNEL_T, *P_P2P_ATTRI_LISTEN_CHANNEL_T; + + +/* P2P 4.1.9 - P2P Group BSSID Attribute */ +typedef struct _P2P_ATTRI_GROUP_BSSID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBssid[MAC_ADDR_LEN]; /* P2P Group BSSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_BSSID_T, *P_P2P_ATTRI_GROUP_BSSID_T; + + +/* P2P 4.1.10 - Extended Listen Timing Attribute */ +typedef struct _P2P_ATTRI_EXT_LISTEN_TIMING_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2AvailPeriod; /* Availability Period */ + UINT_16 u2AvailInterval; /* Availability Interval */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_EXT_LISTEN_TIMING_T, *P_P2P_ATTRI_EXT_LISTEN_TIMING_T; + + +/* P2P 4.1.11 - Intended P2P Interface Address Attribute */ +typedef struct _P2P_ATTRI_INTENDED_IF_ADDR_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucIfAddr[MAC_ADDR_LEN];/* P2P Interface Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTENDED_IF_ADDR_T, *P_P2P_ATTRI_INTENDED_IF_ADDR_T; + + +/* P2P 4.1.12 - P2P Manageability Attribute */ +typedef struct _P2P_ATTRI_MANAGEABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucManageability; /* P2P Manageability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_MANAGEABILITY_T, *P_P2P_ATTRI_MANAGEABILITY_T; + + +/* P2P 4.1.13 - Channel List Attribute */ +typedef struct _P2P_ATTRI_CHANNEL_LIST_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 aucChannelEntry[1]; /* Channel Entry List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CHANNEL_T, *P_P2P_ATTRI_CHANNEL_T; + +typedef struct _CHANNEL_ENTRY_FIELD_T { + UINT_8 ucRegulatoryClass; /* Regulatory Class */ + UINT_8 ucNumberOfChannels; /* Number Of Channels */ + UINT_8 aucChannelList[1]; /* Channel List */ +} __KAL_ATTRIB_PACKED__ CHANNEL_ENTRY_FIELD_T, *P_CHANNEL_ENTRY_FIELD_T; + + +/* P2P 4.1.14 - Notice of Absence Attribute */ +typedef struct _P2P_ATTRI_NOA_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucIndex; /* Index */ + UINT_8 ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ + UINT_8 aucNoADesc[1]; /* NoA Descriptor */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_NOA_T, *P_P2P_ATTRI_NOA_T; + +typedef struct _NOA_DESCRIPTOR_T { + UINT_8 ucCountType; /* Count/Type */ + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} __KAL_ATTRIB_PACKED__ NOA_DESCRIPTOR_T, *P_NOA_DESCRIPTOR_T; + +typedef struct _P2P_ATTRI_DEV_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_INFO_T, *P_P2P_ATTRI_DEV_INFO_T; + +/* WPS 7.1 & 11 WPS TLV Data Format - Device Name */ +typedef struct _DEVICE_NAME_TLV_T { + UINT_16 u2Id; /* WPS Attribute Type */ + UINT_16 u2Length; /* Data Length */ + UINT_8 aucName[32]; /* Device Name */ // TODO: Fixme +} __KAL_ATTRIB_PACKED__ DEVICE_NAME_TLV_T, *P_DEVICE_NAME_TLV_T; + + +/* P2P 4.1.16 - P2P Group Info Attribute */ +typedef struct _P2P_CLIENT_INFO_DESC_T { + UINT_8 ucLength; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_CLIENT_INFO_DESC_T, *P_P2P_CLIENT_INFO_DESC_T; + +typedef struct _P2P_ATTRI_GROUP_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + P2P_CLIENT_INFO_DESC_T arClientDesc[1]; /* P2P Client Info Descriptors */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_INFO_T, *P_P2P_ATTRI_GROUP_INFO_T; + + +/* P2P 4.1.17 - P2P Group ID Attribute */ +typedef struct _P2P_ATTRI_GROUP_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_ID_T, *P_P2P_ATTRI_GROUP_ID_T; + + +/* P2P 4.1.18 - P2P Interface Attribute */ +typedef struct _P2P_ATTRI_INTERFACE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 ucIfAddrCount; /* P2P Interface Address Count */ + UINT_8 aucIfAddrList[MAC_ADDR_LEN];/* P2P Interface Address List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTERFACE_T, *P_P2P_ATTRI_INTERFACE_T; + + +/* P2P 4.1.19 - Operating Channel Attribute */ +typedef struct _P2P_ATTRI_OPERATING_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_OPERATING_CHANNEL_T, *P_P2P_ATTRI_OPERATING_CHANNEL_T; + +/* P2P 4.1.20 - Invitation Flags Attribute */ +typedef struct _P2P_ATTRI_INVITATION_FLAG_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucInviteFlagsBitmap; /* Invitation Flags Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INVITATION_FLAG_T, *P_P2P_ATTRI_INVITATION_FLAG_T; + + + +/* P2P 4.1.1 - General WSC Attribute */ +typedef struct _WSC_ATTRIBUTE_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRIBUTE_T, *P_WSC_ATTRIBUTE_T; + +/* WSC 1.0 Table 28 */ +typedef struct _WSC_ATTRI_VERSION_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucVersion; /* Version 1.0 or 1.1 */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_VERSION_T, *P_WSC_ATTRI_VERSION_T; + +typedef struct _WSC_ATTRI_DEVICE_PASSWORD_ID_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2DevPasswordId; /* Device Password ID */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_DEVICE_PASSWORD_ID_T, *P_WSC_ATTRI_DEVICE_PASSWORD_ID_T; + + +typedef struct _WSC_ATTRI_CONFIGURATION_METHOD_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2ConfigMethods; /* Configure Methods */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_CONFIGURATION_METHOD_T, *P_WSC_ATTRI_CONFIGURATION_METHOD_T; + + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + + +//3 /* --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef UINT_32 (*PFN_APPEND_ATTRI_FUNC)(P_ADAPTER_T, BOOLEAN, PUINT_16, PUINT_8, UINT_16); + +typedef VOID (*PFN_HANDLE_ATTRI_FUNC)(P_SW_RFB_T, P_P2P_ATTRIBUTE_T); + +typedef VOID (*PFN_VERIFY_ATTRI_FUNC)(P_SW_RFB_T, P_P2P_ATTRIBUTE_T, PUINT_16); + +typedef UINT_32 (*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC)(P_ADAPTER_T, P_STA_RECORD_T); + + +typedef struct _APPEND_VAR_ATTRI_ENTRY_T { + UINT_16 u2EstimatedFixedAttriLen; /* For fixed length */ + PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; + PFN_APPEND_ATTRI_FUNC pfnAppendAttri; +} APPEND_VAR_ATTRI_ENTRY_T, *P_APPEND_VAR_ATTRI_ENTRY_T; + +typedef enum _ENUM_CONFIG_METHOD_SEL { + ENUM_CONFIG_METHOD_SEL_AUTO, + ENUM_CONFIG_METHOD_SEL_USER, + ENUM_CONFIG_METHOD_SEL_NUM +} ENUM_CONFIG_METHOD_SEL, *P_ENUM_CONFIG_METHOD_SEL; + +typedef enum _ENUM_P2P_FORMATION_POLICY { + ENUM_P2P_FORMATION_POLICY_AUTO = 0, + ENUM_P2P_FORMATION_POLICY_PASSIVE, /* Device would wait GO NEGO REQ instead of sending it actively. */ + ENUM_P2P_FORMATION_POLICY_NUM +} ENUM_P2P_FORMATION_POLICY, P_ENUM_P2P_FORMATION_POLICY; + +typedef enum _ENUM_P2P_INVITATION_POLICY { + ENUM_P2P_INVITATION_POLICY_USER = 0, + ENUM_P2P_INVITATION_POLICY_ACCEPT_FIRST, + ENUM_P2P_INVITATION_POLICY_DENY_ALL, + ENUM_P2P_INVITATION_POLICY_NUM +} ENUM_P2P_INVITATION_POLICY, P_ENUM_P2P_INVITATION_POLICY; + +//3 /* --------------- Data Structure for P2P Operation --------------- */ +//3 /* Session for CONNECTION SETTINGS of P2P */ +struct _P2P_CONNECTION_SETTINGS_T { + UINT_8 ucDevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + ENUM_P2P_FORMATION_POLICY eFormationPolicy; /* Formation Policy. */ + + /*------------WSC Related Param---------------*/ + UINT_16 u2ConfigMethodsSupport; /* Prefered configure method. + * Some device may not have keypad. + */ + ENUM_CONFIG_METHOD_SEL eConfigMethodSelType; + UINT_16 u2TargetConfigMethod; /* Configure method selected by user or auto. */ + UINT_16 u2LocalConfigMethod; /* Configure method of target. */ + BOOLEAN fgIsPasswordIDRdy; + /*------------WSC Related Param---------------*/ + + UINT_8 ucClientConfigTimeout; + UINT_8 ucGoConfigTimeout; + + UINT_8 ucSecondaryDevTypeCount; +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT]; +#endif + + +#if 0 + UINT_8 ucRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering depends on 802.11mb Annex J. */ + +#endif +#else + UINT_8 ucRfChannelListSize; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; +#endif +#endif + + /* Go Intent */ + UINT_8 ucTieBreaker; + UINT_8 ucGoIntent; + + /* For Device Capability */ + BOOLEAN fgSupportServiceDiscovery; + BOOLEAN fgSupportClientDiscoverability; + BOOLEAN fgSupportConcurrentOperation; + BOOLEAN fgSupportInfraManaged; + BOOLEAN fgSupportInvitationProcedure; + + /* For Group Capability */ + BOOLEAN fgSupportPersistentP2PGroup; + BOOLEAN fgSupportIntraBSSDistribution; + BOOLEAN fgSupportCrossConnection; + BOOLEAN fgSupportPersistentReconnect; + + BOOLEAN fgP2pGroupLimit; + + BOOLEAN fgSupportOppPS; + UINT_16 u2CTWindow; + + BOOLEAN fgIsScanReqIssued; + BOOLEAN fgIsServiceDiscoverIssued; + + + /*============ Target Device Connection Settings ============*/ + + /* Discover Target Device Info. */ + BOOLEAN fgIsDevId; + BOOLEAN fgIsDevType; + + /* Encryption mode of Target Device */ + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + /* SSID + * 1. AP Mode, this is the desired SSID user specified. + * 2. Client Mode, this is the target SSID to be connected to. + */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + + /* Operating channel requested. */ + UINT_8 ucOperatingChnl; + ENUM_BAND_T eBand; + + /* Linten channel requested. */ + UINT_8 ucListenChnl; + + /* For device discover address/type. */ + UINT_8 aucTargetDevAddr[MAC_ADDR_LEN]; /* P2P Device Address, for P2P Device Discovery & P2P Connection. */ + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_DEVICE_DESC_T prTargetP2pDesc; +#endif + + UINT_8 ucLastStatus; /* P2P FSM would append status attribute according to this field. */ + + +#if !CFG_DISABLE_DELAY_PROVISION_DISCOVERY + UINT_8 ucLastDialogToken; + UINT_8 aucIndicateDevAddr[MAC_ADDR_LEN]; +#endif + +#if 0 + UINT_8 ucTargetRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucTargetChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering depends on 802.11mb Annex J. */ +#endif +#endif + +}; + + +typedef struct _NOA_TIMING_T { + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} NOA_TIMING_T, *P_NOA_TIMING_T; + +typedef enum _ENUM_P2P_IOCTL_T { + P2P_IOCTL_IDLE = 0, + P2P_IOCTL_DEV_DISCOVER, + P2P_IOCTL_INVITATION_REQ, + P2P_IOCTL_SERV_DISCOVER, + P2P_IOCTL_WAITING, + P2P_IOCTL_NUM +} ENUM_P2P_IOCTL_T; + + + +/*---------------- Service Discovery Related -------------------*/ +typedef enum _ENUM_SERVICE_TX_TYPE_T { + ENUM_SERVICE_TX_TYPE_BY_DA, + ENUM_SERVICE_TX_TYPE_BY_CHNL, + ENUM_SERVICE_TX_TYPE_NUM +} ENUM_SERVICE_TX_TYPE_T; + + +typedef struct _SERVICE_DISCOVERY_FRAME_DATA_T { + QUE_ENTRY_T rQueueEntry; + P_MSDU_INFO_T prSDFrame; + ENUM_SERVICE_TX_TYPE_T eServiceType; + UINT_8 ucSeqNum; + union { + + UINT_8 ucChannelNum; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + } uTypeData; + BOOLEAN fgIsTxDoneIndicate; +} SERVICE_DISCOVERY_FRAME_DATA_T, *P_SERVICE_DISCOVERY_FRAME_DATA_T; + + + + +struct _P2P_FSM_INFO_T_DEPRECATED { + /* P2P FSM State */ + ENUM_P2P_STATE_T eCurrentState; + + /* Channel */ + BOOLEAN fgIsChannelRequested; + + + + + + + + + + + ENUM_P2P_STATE_T ePreviousState; + + ENUM_P2P_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + + UINT_8 aucTargetIfAddr[PARAM_MAC_ADDR_LEN]; + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + + BOOLEAN fgIsRsponseProbe; /* Indicate if P2P FSM can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfReqMsg; /* Used for SAA FSM request message. */ + + /* Channel Privilege */ + UINT_8 ucSeqNumOfChReq; /* Used for Channel Request message. */ + + + UINT_8 ucSeqNumOfScnMsg; /* Used for SCAN FSM request message. */ + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + UINT_8 ucRxDialogToken; + + /* Timer */ + TIMER_T rDeviceDiscoverTimer; /* For device discovery time of each discovery request from user.*/ + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + + TIMER_T rRejoinTimer; /* A timer used for Action frame timeout usage. */ + + + /* Flag to indicate Provisioning */ + BOOLEAN fgIsConnectionRequested; + + /* Current IOCTL. */ + ENUM_P2P_IOCTL_T eP2pIOCTL; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + /*--------SERVICE DISCOVERY--------*/ + QUE_T rQueueGASRx; /* Input Request/Response. */ + QUE_T rQueueGASTx; /* Output Response. */ + P_SERVICE_DISCOVERY_FRAME_DATA_T prSDRequest; + UINT_8 ucVersionNum; /* GAS packet sequence number for...Action Frame? */ + UINT_8 ucGlobalSeqNum; /* Sequence Number of RX SD packet. */ + /*--------Service DISCOVERY--------*/ + + /*--------DEVICE DISCOVERY---------*/ + UINT_8 aucTargetGroupID[PARAM_MAC_ADDR_LEN]; + UINT_16 u2TargetGroupSsidLen; + UINT_8 aucTargetSsid[32]; + UINT_8 aucSearchingP2pDevice[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDLToken; + /*----------------------------------*/ + + /* Indicating Peer Status. */ + UINT_32 u4Flags; + + /*Indicating current running mode.*/ + BOOLEAN fgIsApMode; + + + /*------------INVITATION------------*/ + ENUM_P2P_INVITATION_POLICY eInvitationRspPolicy; + /*----------------------------------*/ + +}; + + + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + UINT_16 u2SmallestAID; + UINT_16 u2LargestAID; + UINT_8 ucBitmapCtrl; + //UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; + + /* For GC/GO OppPS */ + BOOLEAN fgEnableOppPS; + UINT_16 u2CTWindow; + + /* For GC/GO NOA */ + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + BOOLEAN fgIsNoaAttrExisted; + + /* For P2P Device */ + UINT_8 ucRegClass; /* Regulatory Class for channel. */ + UINT_8 ucListenChannel; /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + + UINT_8 ucPreferredChannel; /* Operating Channel, should be one of channel list in p2p connection settings. */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extened Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + + +#if 0 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + UINT_16 u2IELenForBCN; + UINT_8 aucBeaconIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +// UINT_16 u2IELenForProbeRsp; +// UINT_8 aucProbeRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2IELenForAssocRsp; + UINT_8 aucAssocRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +#else + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2WscAttributeLen; + UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; +#endif + UINT_8 aucGroupID[MAC_ADDR_LEN]; + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUC_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUC_T rOppPsParam; + +}; + + + + + + + +typedef struct _MSG_P2P_DEVICE_DISCOVER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4DevDiscoverTime; /* 0: Infinite, 1~X: in unit of MS. */ + BOOLEAN fgIsSpecificType; +#if CFG_ENABLE_WIFI_DIRECT + P2P_DEVICE_TYPE_T rTargetDeviceType; +#endif + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN]; +} MSG_P2P_DEVICE_DISCOVER_T, *P_MSG_P2P_DEVICE_DISCOVER_T; + + + +typedef struct _MSG_P2P_INVITATION_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; /* Target Device ID to be invited. */ +} MSG_P2P_INVITATION_REQUEST_T, *P_MSG_P2P_INVITATION_REQUEST_T; + +typedef struct _MSG_P2P_FUNCTION_SWITCH_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsFuncOn; +} MSG_P2P_FUNCTION_SWITCH_T, *P_MSG_P2P_FUNCTION_SWITCH_T; + +typedef struct _MSG_P2P_SERVICE_DISCOVERY_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; + BOOLEAN fgNeedTxDoneIndicate; + UINT_8 ucSeqNum; +} MSG_P2P_SERVICE_DISCOVERY_REQUEST_T, *P_MSG_P2P_SERVICE_DISCOVERY_REQUEST_T; + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define p2pChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState = (_eNewMediaState)); + +#define ATTRI_ID(_fp) (((P_P2P_ATTRIBUTE_T) _fp)->ucId) +#define ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[0]) | \ + ((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[1] << 8)) + + +#define ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + ATTRI_LEN(_fp)) + +#define P2P_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += ATTRI_SIZE(_pucAttriBuf)) ) + + +#define P2P_IE(_fp) ((P_IE_P2P_T) _fp) + + +#define WSC_ATTRI_ID(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[1])) + +#define WSC_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[1])) + + +#define WSC_ATTRI_SIZE(_fp) (WSC_ATTRI_HDR_LEN + WSC_ATTRI_LEN(_fp)) + +#define WSC_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WSC_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WSC_ATTRI_SIZE(_pucAttriBuf)) ) + +#define WSC_IE(_fp) ((P_IE_P2P_T) _fp) + + +#define WFD_ATTRI_ID(_fp) (((P_WFD_ATTRIBUTE_T) _fp)->ucElemID) + +#define WFD_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[1])) + +#define WFD_ATTRI_SIZE(_fp) (WFD_ATTRI_HDR_LEN + WFD_ATTRI_LEN(_fp)) + +#define WFD_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WFD_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WFD_ATTRI_SIZE(_pucAttriBuf)) ) + + + + +#if DBG + #define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else + #define ASSERT_BREAK(_exp) +#endif + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*======P2P State======*/ +VOID +p2pStateInit_LISTEN( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prSP2pBssInfo, + IN UINT_8 ucListenChannel + ); + +VOID +p2pStateAbort_LISTEN( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsChannelExtenstion + ); + +VOID +p2pStateAbort_SEARCH_SCAN( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsChannelExtenstion + ); + +VOID +p2pStateAbort_GO_OPERATION( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pStateAbort_GC_OPERATION( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pStateInit_CONFIGURATION( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecBssInfo + ); + +VOID +p2pStateAbort_CONFIGURATION( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pStateInit_JOIN( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pStateAbort_JOIN( + IN P_ADAPTER_T prAdapter + ); + +/*====== P2P Functions ======*/ + + +VOID +p2pFuncInitGO( + IN P_ADAPTER_T prAdapter + ); + + + + + +VOID +p2pFuncDisconnect( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN BOOLEAN fgSendDeauth, + IN UINT_16 u2ReasonCode + ); + +VOID +p2pFuncSwitchOPMode( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN ENUM_OP_MODE_T eOpMode, + IN BOOLEAN fgSyncToFW + ); + +VOID +p2pFuncRunEventProvisioningComplete( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +WLAN_STATUS +p2pFuncSetGroupID( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucGroupID, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen + ); + + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityReqFrame( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucDestAddr[], + IN UINT_8 ucDialogToken + ); + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityRspFrame( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucDestAddr[], + IN UINT_8 ucDialogToken + ); + + +UINT_8 +p2pFuncGetVersionNumOfSD( + IN P_ADAPTER_T prAdapter + ); + +/*====== P2P FSM ======*/ +VOID +p2pFsmRunEventConnectionRequest( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventDeviceDiscoveryRequest( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventDeviceDiscoveryAbort( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventRxGroupNegotiationReqFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationRequestTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationResponseTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationConfirmTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryRequestTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryResponseTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + + +WLAN_STATUS +p2pFsmRunEventInvitationRequestTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + + + +VOID +p2pFsmRunEventRxDeauthentication( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ); + +VOID +p2pFsmRunEventRxDisassociation( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ); + +VOID +p2pFsmRunEventBeaconTimeout( + IN P_ADAPTER_T prAdapter + ); + + + +WLAN_STATUS +p2pFsmRunEventDeauthTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + + +#if 1 +#endif + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +/*======Mail Box Event Message=====*/ + + +VOID +p2pFsmRunEventConnectionAbort( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventConnectionTrigger( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + + +VOID +p2pFsmRunEventP2PFunctionSwitch( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventChGrant( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventJoinComplete( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventConnectionPause( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pIndicationOfMediaStateToHost( + IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, + IN UINT_8 aucTargetAddr[] + ); + +VOID +p2pUpdateBssInfoForJOIN( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prAssocRspSwRfb + ); + +/*======Mail Box Event Message=====*/ + + +VOID +p2pFsmInit( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pFsmUninit( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pFsmSteps( + IN P_ADAPTER_T prAdapter, + IN ENUM_P2P_STATE_T eNextState + ); + +VOID +p2pStartGO( + IN P_ADAPTER_T prAdapter + ); + +VOID +p2pAssignSsid( + IN PUINT_8 pucSsid, + IN PUINT_8 pucSsidLen + ); + +VOID +p2pFsmRunEventScanDone( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +p2pFsmRunEventIOReqTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ); + +VOID +p2pFsmRunEventSearchPeriodTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ); + +VOID +p2pFsmRunEventFsmTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ); + +VOID +p2pFsmRunEventRejoinTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ); + + + + +/*=============== P2P Function Related ================*/ + +/*=============== P2P Function Related ================*/ + + +#if CFG_TEST_WIFI_DIRECT_GO +VOID +p2pTest( + IN P_ADAPTER_T prAdapter + ); +#endif /* CFG_TEST_WIFI_DIRECT_GO */ + + + + +VOID +p2pGenerateP2P_IEForBeacon( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +p2pGenerateP2P_IEForAssocReq( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +p2pGenerateP2P_IEForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +VOID +p2pGenerateP2P_IEForProbeReq( + IN P_ADAPTER_T prAdapter, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + + + +UINT_32 +p2pCalculateP2P_IELenForBeacon( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +UINT_32 +p2pCalculateP2P_IELenForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +UINT_32 +p2pCalculateP2P_IELenForProbeReq( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + + +VOID +p2pGenerateWSC_IEForProbeResp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +p2pGenerateWSC_IEForProbeReq( + IN P_ADAPTER_T prAdapter, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + + +UINT_16 +p2pCalculateWSC_IELenForProbeReq( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +UINT_32 +p2pCalculateWSC_IELenForProbeResp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +UINT_32 +p2pAppendAttriStatus( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + + +UINT_32 +p2pAppendAttriCapability( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriGoIntent( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriCfgTimeout( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriGroupBssid( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + +UINT_32 +p2pAppendAttriDeviceIDForBeacon( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriDeviceIDForProbeReq( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriDeviceIDForDeviceDiscoveryReq( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriListenChannel( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriIntendP2pIfAddr( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + +UINT_32 +p2pAppendAttriChannelList( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pCalculateAttriLenChannelList( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +UINT_32 +p2pAppendAttriNoA( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriDeviceInfo( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pCalculateAttriLenDeviceInfo( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +UINT_32 +p2pAppendAttriGroupInfo( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pCalculateAttriLenGroupInfo( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + + +UINT_32 +p2pAppendAttriP2pGroupID( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriOperatingChannel( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriInvitationFlag( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + +VOID +p2pGenerateWscIE ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ); + +UINT_32 +p2pAppendAttriWSCConfigMethod ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriWSCVersion ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriWSCGONegReqDevPasswordId ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +p2pAppendAttriWSCGONegRspDevPasswordId ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +WLAN_STATUS +p2pGetWscAttriList( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + OUT PPUINT_8 ppucAttriList, + OUT PUINT_16 pu2AttriListLen + ); + +WLAN_STATUS +p2pGetAttriList ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + OUT PPUINT_8 ppucAttriList, + OUT PUINT_16 pu2AttriListLen + ); + +VOID +p2pRunEventAAATxFail ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +WLAN_STATUS +p2pRunEventAAASuccess ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + + +WLAN_STATUS +p2pRunEventAAAComplete ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +WLAN_STATUS +p2pSendProbeResponseFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +BOOLEAN +p2pFsmRunEventRxProbeRequestFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +p2pFsmRunEventRxProbeResponseFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_BSS_DESC_T prBssDesc + ); + +WLAN_STATUS +p2pRxPublicActionFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +p2pRxActionFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +p2pFsmRunEventRxGroupNegotiationRspFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +p2pFsmRunEventRxGroupNegotiationCfmFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + + +#if 0 // frog +BOOLEAN +scanMatchFilterOfP2P ( + IN P_SW_RFB_T prSWRfb, + IN PP_BSS_DESC_T pprBssDesc + ); +#endif // frog + +VOID +p2pProcessEvent_UpdateNOAParam ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam + ); + +VOID +p2pFuncCompleteIOCTL( + IN P_ADAPTER_T prAdapter, + IN WLAN_STATUS rWlanStatus + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +__KAL_INLINE__ VOID +p2pDataTypeCheck ( + VOID + ) +{ + DATA_STRUC_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2+4+1)); // all UINT_8 + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3+1)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3+1)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3+1)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3+2)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3+6)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3+1)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3+2)); +#if CID52_53_54 + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3+5)); +#else + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3+5)); +#endif + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3+6)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3+4)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3+6)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3+1)); + + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3+4)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3+3)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13); + DATA_STRUC_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3+6+2+8+1+8)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4+32)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1+6+6+1+2+8+1+8)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3+(1+6+6+1+2+8+1+8))); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3+38)); + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3+13)); +#if CID52_53_54 + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3+5)); +#else + DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3+5)); +#endif + + + return; +} +#endif /* _lint */ + +#endif /* _P2P_FSM_H */ + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h new file mode 100755 index 000000000000..d7676058572a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h @@ -0,0 +1,350 @@ +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + + +VOID +p2pFuncRequestScan( + IN P_ADAPTER_T prAdapter, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo + ); + +VOID +p2pFuncCancelScan( + IN P_ADAPTER_T prAdapter, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo + ); + + + +VOID +p2pFuncStartGO( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucSsidBuf, + IN UINT_8 ucSsidLen, + IN UINT_8 ucChannelNum, + IN ENUM_BAND_T eBand, + IN ENUM_CHNL_EXT_T eSco, + IN BOOLEAN fgIsPureAP + ); + + + +VOID +p2pFuncAcquireCh( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ); + + +VOID +p2pFuncReleaseCh( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ); + +VOID +p2pFuncSetChannel( + IN P_ADAPTER_T prAdapter, + IN P_RF_CHANNEL_INFO_T prRfChannelInfo + ); + + +BOOLEAN +p2pFuncRetryJOIN( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_P2P_JOIN_INFO_T prJoinInfo + ); + +VOID +p2pFuncUpdateBssInfoForJOIN ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prAssocRspSwRfb + ); + + +WLAN_STATUS +p2pFuncTxMgmtFrame( + IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, + IN P_MSDU_INFO_T prMgmtTxMsdu, + IN UINT_64 u8Cookie + ); + +WLAN_STATUS +p2pFuncBeaconUpdate( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, + IN PUINT_8 pucNewBcnHdr, + IN UINT_32 u4NewHdrLen, + IN PUINT_8 pucNewBcnBody, + IN UINT_32 u4NewBodyLen + ); + + +BOOLEAN +p2pFuncValidateAuth( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PP_STA_RECORD_T pprStaRec, + OUT PUINT_16 pu2StatusCode + ); + +BOOLEAN +p2pFuncValidateAssocReq( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ); + + +VOID +p2pFuncResetStaRecStatus( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +VOID +p2pFuncInitConnectionSettings( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings + ); + + +BOOLEAN +p2pFuncParseCheckForP2PInfoElem( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, + OUT PUINT_8 pucOuiType + ); + + +BOOLEAN +p2pFuncValidateProbeReq( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ); + +VOID +p2pFuncValidateRxActionFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +BOOLEAN +p2pFuncIsAPMode( + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + + +VOID +p2pFuncParseBeaconContent( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN PUINT_8 pucIEInfo, + IN UINT_32 u4IELen + ); + + +P_BSS_DESC_T +p2pFuncKeepOnConnection( + + IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo + ); + + +VOID +p2pFuncStoreAssocRspIEBuffer( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + + +VOID +p2pFuncMgmtFrameRegister( + IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, + IN BOOLEAN fgIsRegistered, + OUT PUINT_32 pu4P2pPacketFilter + ); + +VOID +p2pFuncUpdateMgmtFrameRegister( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4OsFilter + ); + + +VOID +p2pFuncGetStationInfo( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucMacAddr, + OUT P_P2P_STATION_INFO_T prStaInfo + ); + +BOOLEAN +p2pFuncGetAttriList( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + OUT PPUINT_8 ppucAttriList, + OUT PUINT_16 pu2AttriListLen + ); + +P_MSDU_INFO_T +p2pFuncProcessP2pProbeRsp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMgmtTxMsdu + ); + +#if 0 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +VOID +p2pFuncGenerateExtra_IEForBeacon( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +VOID +p2pFuncGenerateP2p_IEForBeacon( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +VOID +p2pFuncGenerateWSC_IEForBeacon( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); +#endif +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +VOID +p2pFuncGenerateP2p_IEForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +VOID +p2pFuncGenerateWSC_IEForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + + +UINT_32 +p2pFuncCalculateP2P_IELen( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ); + +VOID +p2pFuncGenerateP2P_IE( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ); + + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + + +UINT_32 +p2pFuncAppendAttriExtListenTiming( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +VOID +p2pFuncDissolve( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN BOOLEAN fgSendDeauth, + IN UINT_16 u2ReasonCode + ); + + +P_IE_HDR_T +p2pFuncGetSpecIE( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2BufferLen, + IN UINT_8 ucElemID, + IN PBOOLEAN pfgIsMore + ); + + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2BufferLen, + IN UINT_16 u2AttriID + ); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h new file mode 100755 index 000000000000..e6320542aaed --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h @@ -0,0 +1,232 @@ +#ifndef _P2P_IE_H +#define _P2P_IE_H + +#if CFG_SUPPORT_WFD + +#define ELEM_MAX_LEN_WFD 62 // TODO: Move to appropriate place + + +/*---------------- WFD Data Element Definitions ----------------*/ +/* WFD 4.1.1 - WFD IE format */ +#define WFD_OUI_TYPE_LEN 4 +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, aucP2PAttributes[0]) */ + +/* WFD 4.1.1 - General WFD Attribute */ +#define WFD_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ + +/* WFD Attribute Code */ +#define WFD_ATTRI_ID_DEV_INFO 0 +#define WFD_ATTRI_ID_ASSOC_BSSID 1 +#define WFD_ATTRI_ID_COUPLED_SINK_INFO 6 +#define WFD_ATTRI_ID_EXT_CAPABILITY 7 +#define WFD_ATTRI_ID_SESSION_INFO 9 +#define WFD_ATTRI_ID_ALTER_MAC_ADDRESS 10 + +/* Maximum Length of WFD Attributes */ +#define WFD_ATTRI_MAX_LEN_DEV_INFO 6 /* 0 */ +#define WFD_ATTRI_MAX_LEN_ASSOC_BSSID 6 /* 1 */ +#define WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO 7 /* 6 */ +#define WFD_ATTRI_MAX_LEN_EXT_CAPABILITY 2 /* 7 */ +#define WFD_ATTRI_MAX_LEN_SESSION_INFO 0 /* 9 */ /* 24 * #Clients */ +#define WFD_ATTRI_MAX_LEN_ALTER_MAC_ADDRESS 6 /* 10 */ + + + + + +/* WFD 1.10 5.1.1 */ +typedef struct _IE_WFD_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucWFDAttributes[1]; /* WFD Subelement */ +} __KAL_ATTRIB_PACKED__ IE_WFD_T, *P_IE_WFD_T; + +typedef struct _WFD_ATTRIBUTE_T { + UINT_8 ucElemID; /* Subelement ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WFD_ATTRIBUTE_T, *P_WFD_ATTRIBUTE_T; + +typedef struct _WFD_DEVICE_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdDevInfo; + UINT_16 u2SessionMgmtCtrlPort; + UINT_16 u2WfdDevMaxSpeed; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_IE_T, *P_WFD_DEVICE_INFORMATION_IE_T; + +typedef struct _WFD_ASSOCIATED_BSSID_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_ASSOCIATED_BSSID_IE_T, *P_WFD_ASSOCIATED_BSSID_IE_T; + +typedef struct _WFD_COUPLE_SINK_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_COUPLE_SINK_INFORMATION_IE_T, *P_WFD_COUPLE_SINK_INFORMATION_IE_T; + +typedef struct _WFD_EXTENDED_CAPABILITY_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdExtCapabilityBp; +} +__KAL_ATTRIB_PACKED__ WFD_EXTENDED_CAPABILITY_IE_T, *P_WFD_EXTENDED_CAPABILITY_IE_T; + +typedef struct _WFD_SESSION_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + PUINT_8 pucWfdDevInfoDesc[1]; +} __KAL_ATTRIB_PACKED__ WFD_SESSION_INFORMATION_IE_T, *P_WFD_SESSION_INFORMATION_IE_T; + +typedef struct _WFD_DEVICE_INFORMATION_DESCRIPTOR_T { + UINT_8 ucLength; + UINT_8 aucDevAddr[MAC_ADDR_LEN]; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdDevMaxSpeed; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_DESCRIPTOR_T, *P_WFD_DEVICE_INFORMATION_DESCRIPTOR_T; + + +#endif + + +UINT_32 +p2pCalculate_IEForAssocReq( + + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +VOID +p2pGenerate_IEForAssocReq( + + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +#if CFG_SUPPORT_WFD + +UINT_32 +wfdFuncAppendAttriDevInfo( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +wfdFuncAppendAttriAssocBssid( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +wfdFuncAppendAttriExtCapability( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +wfdFuncCalculateAttriLenSessionInfo( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +UINT_32 +wfdFuncAppendAttriSessionInfo( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ); + +UINT_32 +wfdFuncCalculateWfdIELenForProbeResp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + +VOID +wfdFuncGenerateWfdIEForProbeResp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +UINT_32 +wfdFuncCalculateWfdIELenForAssocReq( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +VOID +wfdFuncGenerateWfdIEForAssocReq( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +VOID +wfdFuncGenerateWfdIEForAssocRsp( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +UINT_32 +wfdFuncCalculateWfdIELenForBeacon( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + +VOID +wfdFuncGenerateWfdIEForBeacon( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +#endif + + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h new file mode 100755 index 000000000000..fe20ac38048f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h @@ -0,0 +1,109 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm.h#1 $ +*/ + +/*! \file "rlm.h" + \brief +*/ + + + + +#ifndef _P2P_RLM_H +#define _P2P_RLM_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +VOID +rlmBssInitForAP( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +BOOLEAN +rlmUpdateBwByChListForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +VOID +rlmUpdateParamsForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + BOOLEAN fgUpdateBeacon + ); + +VOID +rlmFuncInitialChannelList( + IN P_ADAPTER_T prAdapter + ); + +VOID +rlmFuncCommonChannelList( + IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, + IN UINT_8 ucChannelListSize + ); + +UINT_8 +rlmFuncFindOperatingClass( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucChannelNum + ); + +BOOLEAN +rlmFuncFindAvailableChannel( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, + IN BOOLEAN fgIsSocialChannel, + IN BOOLEAN fgIsDefaultChannel + ); + +ENUM_CHNL_EXT_T +rlmDecideScoForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h new file mode 100755 index 000000000000..fa93d94decde --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,93 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm_obss.h#1 $ +*/ + +/*! \file "rlm_obss.h" + \brief +*/ + + + +#ifndef _P2P_RLM_OBSS_H +#define _P2P_RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +rlmRspGenerateObssScanIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmProcessPublicAction ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ); + +VOID +rlmProcessHtAction ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ); + +VOID +rlmHandleObssStatusEventPkt ( + P_ADAPTER_T prAdapter, + P_EVENT_AP_OBSS_STATUS_T prObssStatus + ); + +UINT_8 +rlmObssChnlLevel ( + P_BSS_INFO_T prBssInfo, + ENUM_BAND_T eBand, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ); + +VOID +rlmObssScanExemptionRsp ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb + ); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h new file mode 100755 index 000000000000..8ba3199f4b02 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h @@ -0,0 +1,127 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_scan.h#1 $ +*/ + +/*! \file "scan.h" + \brief + +*/ + + + + +#ifndef _P2P_SCAN_H +#define _P2P_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +WLAN_STATUS +scanSendDeviceDiscoverEvent ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_SW_RFB_T prSwRfb + ); + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucDeviceID[], + IN PP_BSS_DESC_T pprBssDesc + ); + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], + IN BOOLEAN fgIsDeviceAddr, + IN BOOLEAN fgAddIfNoFound + ); + +P_P2P_DEVICE_DESC_T +scanGetP2pDeviceDesc( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +scnEventReturnChannel( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucScnSeqNum + ); + +BOOLEAN +scanUpdateP2pDeviceDesc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +scanP2pProcessBeaconAndProbeResp( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, + IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame + ); + +VOID +scanRemoveAllP2pBssDesc( + P_ADAPTER_T prAdapter + ); + +VOID +scanRemoveP2pBssDesc( + P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ); + + +P_BSS_DESC_T +scanP2pSearchDesc( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo + ); + + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h new file mode 100755 index 000000000000..22bcf1798ce3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h @@ -0,0 +1,89 @@ +#ifndef _P2P_STATE_H +#define _P2P_STATE_H + +BOOLEAN +p2pStateInit_IDLE( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + OUT P_ENUM_P2P_STATE_T peNextState + ); + + +VOID +p2pStateAbort_IDLE( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ); + +VOID +p2pStateInit_SCAN( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + +VOID +p2pStateAbort_SCAN( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ); + +VOID +p2pStateInit_AP_CHANNEL_DETECT( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + +VOID +p2pStateAbort_AP_CHANNEL_DETECT( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, + IN ENUM_P2P_STATE_T eNextState + ); + +VOID +p2pStateInit_CHNL_ON_HAND( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + +VOID +p2pStateAbort_CHNL_ON_HAND( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + IN ENUM_P2P_STATE_T eNextState + ); + + +VOID +p2pStateAbort_REQING_CHANNEL( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ); + + +VOID +p2pStateInit_GC_JOIN( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +p2pStateAbort_GC_JOIN( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, + IN ENUM_P2P_STATE_T eNextState + ); + +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h new file mode 100755 index 000000000000..8f6ffd131803 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h @@ -0,0 +1,288 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/privacy.h#1 $ +*/ + +/*! \file privacy.h + \brief This file contains the function declaration for privacy.c. +*/ + + + +/* +** $Log: privacy.h $ + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 25 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * For support the WHQL test, do the remove key code refine. + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the cmd return type + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for auth mode and encryption status setting from build connection command + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for wapi + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the tx done callback handle function + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for mac header privacy bit setting + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the structure for parsing the EAPoL frame + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the class error function parameter + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security function declaration + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the ap selection structure + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +#ifndef _PRIVACY_H +#define _PRIVACY_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_KEY_NUM 4 +#define WEP_40_LEN 5 +#define WEP_104_LEN 13 +#define LEGACY_KEY_MAX_LEN 16 +#define CCMP_KEY_LEN 16 +#define TKIP_KEY_LEN 32 +#define MAX_KEY_LEN 32 +#define MIC_RX_KEY_OFFSET 16 +#define MIC_TX_KEY_OFFSET 24 +#define MIC_KEY_LEN 8 + +#define WEP_KEY_ID_FIELD BITS(0,29) +#define KEY_ID_FIELD BITS(0,7) + +#define IS_TRANSMIT_KEY BIT(31) +#define IS_UNICAST_KEY BIT(30) +#define IS_AUTHENTICATOR BIT(28) + +#define CIPHER_SUITE_NONE 0 +#define CIPHER_SUITE_WEP40 1 +#define CIPHER_SUITE_TKIP 2 +#define CIPHER_SUITE_TKIP_WO_MIC 3 +#define CIPHER_SUITE_CCMP 4 +#define CIPHER_SUITE_WEP104 5 +#define CIPHER_SUITE_BIP 6 +#define CIPHER_SUITE_WEP128 7 +#define CIPHER_SUITE_WPI 8 + +#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ +#define WPA_KEY_INFO_MIC BIT(8) +#define WPA_KEY_INFO_SECURE BIT(9) + +#define MASK_2ND_EAPOL (WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC) + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _IEEE_802_1X_HDR { + UINT_8 ucVersion; + UINT_8 ucType; + UINT_16 u2Length; + /* followed by length octets of data */ +} IEEE_802_1X_HDR, *P_IEEE_802_1X_HDR; + +typedef struct _EAPOL_KEY { + UINT_8 ucType; + /* Note: key_info, key_length, and key_data_length are unaligned */ + UINT_8 aucKeyInfo[2]; /* big endian */ + UINT_8 aucKeyLength[2]; /* big endian */ + UINT_8 aucReplayCounter[8]; + UINT_8 aucKeyNonce[16]; + UINT_8 aucKeyIv[16]; + UINT_8 aucKeyRsc[8]; + UINT_8 aucKeyId[8]; /* Reserved in IEEE 802.11i/RSN */ + UINT_8 aucKeyMic[16]; + UINT_8 aucKeyDataLength[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +} EAPOL_KEY, *P_EAPOL_KEY; + +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; + +#if 0 +/* WPA2 PMKID cache structure */ +typedef struct _PMKID_ENTRY_T { + PARAM_BSSID_INFO_T rBssidInfo; + BOOLEAN fgPmkidExist; +} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +secInit( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucNetTypeIdx + ); + +VOID +secSetPortBlocked( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + IN BOOLEAN fgPort + ); + +BOOL +secCheckClassError( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_STA_RECORD_T prStaRec + ); + +BOOL +secTxPortControlCheck( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec + ); + +BOOLEAN +secRxPortControlCheck( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSWRfb + ); + +VOID +secSetCipherSuite( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4CipherSuitesFlags + ); + +BOOL +secProcessEAPOL( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucPayload, + IN UINT_16 u2PayloadLen + ); + +VOID +secHandleTxDoneCallback( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T pMsduInfo, + IN P_STA_RECORD_T prStaRec, + IN WLAN_STATUS rStatus + ); + +BOOLEAN +secIsProtectedFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsdu, + IN P_STA_RECORD_T prStaRec + ); + +VOID +secClearPmkid( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +secRsnKeyHandshakeEnabled( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +secTransmitKeyExist( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +BOOLEAN +secEnabledInAis( + IN P_ADAPTER_T prAdapter + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRIVACY_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h new file mode 100755 index 000000000000..74c4bb0fc440 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h @@ -0,0 +1,111 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rate.h#1 $ +*/ + +/*! \file rate.h + \brief This file contains the rate utility function of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: rate.h $ + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _RATE_H +#define _RATE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in rate.c */ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs ( + IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, + OUT PBOOLEAN pfgIsUnknownBSSBasicRate + ); + +VOID +rateGetDataRatesFromRateSet ( + IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, + OUT PUINT_8 pucDataRates, + OUT PUINT_8 pucDataRatesLen + ); + +BOOLEAN +rateGetHighestRateIndexFromRateSet ( + IN UINT_16 u2RateSet, + OUT PUINT_8 pucHighestRateIndex + ); + +BOOLEAN +rateGetLowestRateIndexFromRateSet ( + IN UINT_16 u2RateSet, + OUT PUINT_8 pucLowestRateIndex + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RATE_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h new file mode 100755 index 000000000000..197202f73e76 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h @@ -0,0 +1,451 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm.h#2 $ +*/ + +/*! \file "rlm.h" + \brief +*/ + + + +/* +** $Log: rlm.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 13 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Use SCO of BSS_INFO to replace user-defined setting variables + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 18 2010 cm.chang + * [WCXRP00000114] [MT6620 Wi-Fi] [Driver] Fix compiling warning in Linux about RLM network index checking + * Enum member cannot be used as compiling option decision in Linux + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX HT GF compiling option + * + * 06 02 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Roll back to remove CFG_SUPPORT_BCM_TEST. + * + * 06 01 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Update BCM Test and RW configuration. + * + * 05 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some compiling options to control 11n functions + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 17 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * MT6620 does not support L-SIG TXOP + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Move default value of HT capability to rlm.h + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * + * Modify the prototype of rlmRecAssocRspHtInfo() + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add several function prototypes for HT operation + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +#ifndef _RLM_H +#define _RLM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ELEM_EXT_CAP_DEFAULT_VAL \ + (ELEM_EXT_CAP_20_40_COEXIST_SUPPORT /*| ELEM_EXT_CAP_PSMP_CAP*/) + + +#if CFG_SUPPORT_RX_STBC + #define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_1_SS +#else + #define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_NO_SUPPORTED +#endif + +#if CFG_SUPPORT_RX_SGI + #define FIELD_HT_CAP_INFO_SGI_20M HT_CAP_INFO_SHORT_GI_20M + #define FIELD_HT_CAP_INFO_SGI_40M HT_CAP_INFO_SHORT_GI_40M +#else + #define FIELD_HT_CAP_INFO_SGI_20M 0 + #define FIELD_HT_CAP_INFO_SGI_40M 0 +#endif + +#if CFG_SUPPORT_RX_HT_GF + #define FIELD_HT_CAP_INFO_HT_GF HT_CAP_INFO_HT_GF +#else + #define FIELD_HT_CAP_INFO_HT_GF 0 +#endif + +#define HT_CAP_INFO_DEFAULT_VAL \ + (HT_CAP_INFO_SUP_CHNL_WIDTH | FIELD_HT_CAP_INFO_HT_GF | \ + FIELD_HT_CAP_INFO_SGI_20M | FIELD_HT_CAP_INFO_SGI_40M | \ + FIELD_HT_CAP_INFO_RX_STBC | HT_CAP_INFO_DSSS_CCK_IN_40M) + + + +#define AMPDU_PARAM_DEFAULT_VAL \ + (AMPDU_PARAM_MAX_AMPDU_LEN_64K | AMPDU_PARAM_MSS_NO_RESTRICIT) + + +#define SUP_MCS_TX_DEFAULT_VAL \ + SUP_MCS_TX_SET_DEFINED /* TX defined and TX/RX equal (TBD) */ + +#if CFG_SUPPORT_MFB + #define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_BOTH +#else + #define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_NO_FB +#endif + +#if CFG_SUPPORT_RX_RDG + #define FIELD_HT_EXT_CAP_RDR HT_EXT_CAP_RD_RESPONDER +#else + #define FIELD_HT_EXT_CAP_RDR 0 +#endif + +#if CFG_SUPPORT_MFB || CFG_SUPPORT_RX_RDG + #define FIELD_HT_EXT_CAP_HTC HT_EXT_CAP_HTC_SUPPORT +#else + #define FIELD_HT_EXT_CAP_HTC 0 +#endif + +#define HT_EXT_CAP_DEFAULT_VAL \ + (HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE | \ + FIELD_HT_EXT_CAP_MFB | FIELD_HT_EXT_CAP_HTC | \ + FIELD_HT_EXT_CAP_RDR) + +#define TX_BEAMFORMING_CAP_DEFAULT_VAL 0 +#define ASEL_CAP_DEFAULT_VAL 0 + + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* It is used for RLM module to judge if specific network is valid + * Note: Ad-hoc mode of AIS is not included now. (TBD) + */ +#define RLM_NET_PARAM_VALID(_prBssInfo) \ + (IS_BSS_ACTIVE(_prBssInfo) && \ + ((_prBssInfo)->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_ACCESS_POINT || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_IBSS || \ + RLM_NET_IS_BOW(_prBssInfo)) \ + ) + +#define RLM_NET_IS_11N(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11N) +#define RLM_NET_IS_11GN(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11GN) + + +/* This macro is used to sweep all 3 networks */ +#define RLM_NET_FOR_EACH(_ucNetIdx) \ + for ((_ucNetIdx) = 0; \ + (_ucNetIdx) < NETWORK_TYPE_INDEX_NUM; \ + (_ucNetIdx)++) + +/* This macro is used to sweep all networks excluding BOW */ +#if CFG_ENABLE_BT_OVER_WIFI + /* Note: value of enum NETWORK_TYPE_BOW_INDEX is validated in + * rlmStuctureCheck(). + */ + #define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) \ + for ((_ucNetIdx) = 0; \ + (_ucNetIdx) < NETWORK_TYPE_BOW_INDEX; \ + (_ucNetIdx)++) + + #define RLM_NET_IS_BOW(_prBssInfo) \ + ((_prBssInfo)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + +#else + #define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) RLM_NET_FOR_EACH(_ucNetIdx) + #define RLM_NET_IS_BOW(_prBssInfo) (FALSE) + +#endif /* end of CFG_ENABLE_BT_OVER_WIFI */ + + +/* The bandwidth modes are not used anymore. They represent if AP + * can use 20/40 bandwidth, not all modes. (20110411) + */ +#define RLM_AP_IS_BW_40_ALLOWED(_prAdapter, _prBssInfo) \ + (((_prBssInfo)->eBand == BAND_2G4 && \ + (_prAdapter)->rWifiVar.rConnSettings.uc2G4BandwidthMode \ + == CONFIG_BW_20_40M) || \ + ((_prBssInfo)->eBand == BAND_5G && \ + (_prAdapter)->rWifiVar.rConnSettings.uc5GBandwidthMode \ + == CONFIG_BW_20_40M)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +rlmFsmEventInit ( + P_ADAPTER_T prAdapter + ); + +VOID +rlmFsmEventUninit ( + P_ADAPTER_T prAdapter + ); + +VOID +rlmReqGenerateHtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmReqGenerateExtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmRspGenerateHtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmRspGenerateExtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmRspGenerateHtOpIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmRspGenerateErpIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +VOID +rlmProcessBcn ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +VOID +rlmProcessAssocRsp ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +VOID +rlmFillSyncCmdParam ( + P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, + P_BSS_INFO_T prBssInfo + ); + +VOID +rlmSyncOperationParams ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +VOID +rlmBssInitForAPandIbss ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +VOID +rlmProcessAssocReq ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +VOID +rlmBssAborted ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +__KAL_INLINE__ VOID +rlmDataTypeCheck ( + VOID + ) +{ +#if CFG_ENABLE_BT_OVER_WIFI + DATA_STRUC_INSPECTING_ASSERT( + NETWORK_TYPE_AIS_INDEX < NETWORK_TYPE_BOW_INDEX); + + #if CFG_ENABLE_WIFI_DIRECT + DATA_STRUC_INSPECTING_ASSERT( + NETWORK_TYPE_P2P_INDEX < NETWORK_TYPE_BOW_INDEX); + #endif +#endif + + return; +} +#endif /* _lint */ + +#endif /* _RLM_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h new file mode 100755 index 000000000000..fda01372bf37 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h @@ -0,0 +1,358 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_domain.h#1 $ +*/ + +/*! \file "rlm_domain.h" + \brief +*/ + + + +/* +** $Log: rlm_domain.h $ + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Provide legal channel function based on domain + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 01 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide query function about full channle list. + * + * Dec 1 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Declare public rDomainInfo + * +** +*/ + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SUBBAND_NUM 6 + + +#define COUNTRY_CODE_NULL ((UINT_16)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ +#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua/Barbuda */ +#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ +#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Argentina */ +#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ +#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ +#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ +#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ +#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ +#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ +#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ +#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ +#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ +#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ +#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ +#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ +#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ +#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ +#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Colombia */ +#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ +#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ +#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ +#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ +#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ +#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ +#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ +#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ +#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ +#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* ETSI (Europe) */ +#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ +#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ +#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ +#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ +#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ +#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ +#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ +#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ +#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ +#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ +#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ +#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ +#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ +#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ +#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ +#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jamaica */ +#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ +#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ +#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ +#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ +#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ +#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ +#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ +#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxembourg */ +#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ +#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ +#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ +#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ +#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ +#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ +#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ +#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ +#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ +#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ +#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ +#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ +#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ +#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico */ +#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ +#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ +#define COUNTRY_CODE_PZ (((UINT_16) 'P' << 8) | (UINT_16) 'Z') /* Panama */ +#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russian */ +#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ +#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ +#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapore */ +#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ +#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ +#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ +#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ +#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad */ +#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ +#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* United States */ +#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ +#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent */ +#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ +#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Define channel offset in unit of 5MHz bandwidth */ +typedef enum _ENUM_CHNL_SPAN_T { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; + +/* Define BSS operating bandwidth */ +typedef enum _ENUM_CHNL_BW_T { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; + +#if 0 +/* If channel width is CHNL_BW_20_40, the first channel will be SCA and + * the second channel is SCB, then iteratively. + * Note the final channel will not be SCA. + */ +typedef struct _DOMAIN_SUBBAND_INFO { + UINT_8 ucRegClass; + ENUM_BAND_T eBand; + ENUM_CHNL_SPAN_T eChannelSpan; + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + ENUM_CHNL_BW_T eChannelBw; + BOOLEAN fgDfsNeeded; + BOOLEAN fgIbssProhibited; +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + UINT_16 u2CountryCode; + UINT_16 u2MibRegDomainValue; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; + +#else /* New definition 20110830 */ + +/* In all bands, the first channel will be SCA and the second channel is SCB, + * then iteratively. + * Note the final channel will not be SCA. + */ +typedef struct _DOMAIN_SUBBAND_INFO { + /* Note1: regulation class depends on operation bandwidth and RF band. + * For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81 + * 2.4GHz, 1~13, SCA ==> regulation class = 83 + * 2.4GHz, 1~13, SCB ==> regulation class = 84 + * Note2: TX power limit is not specified here because path loss is unknown + */ + UINT_8 ucRegClass; /* Regulation class for 20MHz */ + UINT_8 ucBand; /* Type: ENUM_BAND_T */ + UINT_8 ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 ucReserved; /* Type: BOOLEAN (fgDfsNeeded) */ +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + PUINT_16 pu2CountryGroup; + UINT_32 u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; +#endif + +/* The following definitions are not used yet */ +typedef enum _ENUM_CH_SET_2G4_T { + CH_SET_2G4_NA, + CH_SET_2G4_1_11, + CH_SET_2G4_1_13, + CH_SET_2G4_1_14, + CH_SET_2G4_NUM +} ENUM_CH_SET_2G4_T, *P_ENUM_CH_SET_2G4_T; + +typedef enum _ENUM_CH_SET_UNII_LOW_T { + CH_SET_UNII_LOW_NA, + CH_SET_UNII_LOW_36_48, + CH_SET_UNII_LOW_NUM +} ENUM_CH_SET_UNII_LOW_T, *P_ENUM_CH_SET_UNII_LOW_T; + +typedef enum _ENUM_CH_SET_UNII_MID_T { + CH_SET_UNII_MID_NA, + CH_SET_UNII_MID_52_64, + CH_SET_UNII_MID_NUM +} ENUM_CH_SET_UNII_MID_T, *P_ENUM_CH_SET_UNII_MID_T; + +typedef enum _ENUM_CH_SET_UNII_WW_T { + CH_SET_UNII_WW_NA, + CH_SET_UNII_WW_100_128, + CH_SET_UNII_WW_100_140, + CH_SET_UNII_WW_100_116_132_140, + CH_SET_UNII_WW_NUM +} ENUM_CH_SET_UNII_WW_T, *P_ENUM_CH_SET_UNII_WW_T; + +typedef enum _ENUM_CH_SET_UNII_UPPER_T { + CH_SET_UNII_UPPER_NA, + CH_SET_UNII_UPPER_149_161, + CH_SET_UNII_UPPER_149_165, + CH_SET_UNII_UPPER_149_173, + CH_SET_UNII_UPPER_NUM +} ENUM_CH_SET_UNII_UPPER_T, *P_ENUM_CH_SET_UNII_UPPER_T; + +typedef struct _COUNTRY_CH_SET_T { + ENUM_CH_SET_2G4_T e2G4; + ENUM_CH_SET_UNII_LOW_T eUniiLow; + ENUM_CH_SET_UNII_MID_T eUniiMid; + ENUM_CH_SET_UNII_WW_T eUniiWw; + ENUM_CH_SET_UNII_UPPER_T eUniiUpper; +} COUNTRY_CH_SET_T, *P_COUNTRY_CH_SET_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +P_DOMAIN_INFO_ENTRY +rlmDomainGetDomainInfo ( + P_ADAPTER_T prAdapter + ); + +VOID +rlmDomainGetChnlList ( + P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, + UINT_8 ucMaxChannelNum, + PUINT_8 pucNumOfChannel, + P_RF_CHANNEL_INFO_T paucChannelList + ); + +VOID +rlmDomainSendCmd ( + P_ADAPTER_T prAdapter, + BOOLEAN fgIsOid + ); + +BOOLEAN +rlmDomainIsLegalChannel ( + P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, + UINT_8 ucChannel + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_DOMAIN_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h new file mode 100755 index 000000000000..20533c95762f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h @@ -0,0 +1,164 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_obss.h#1 $ +*/ + +/*! \file "rlm_obss.h" + \brief +*/ + + + +/* +** $Log: rlm_obss.h $ + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +#ifndef _RLM_OBSS_H +#define _RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + + +#define CHNL_LEVEL0 0 +#define CHNL_LEVEL1 1 +#define CHNL_LEVEL2 2 + +#define AFFECTED_CHNL_OFFSET 5 + +#define OBSS_SCAN_MIN_INTERVAL 10 /* In unit of sec */ + +#define PUBLIC_ACTION_MAX_LEN 200 /* In unit of byte */ + +/* P2P GO only */ +/* Define default OBSS Scan parameters (from MIB in spec.) */ +#define dot11OBSSScanPassiveDwell 20 +#define dot11OBSSScanActiveDwell 10 +#define dot11OBSSScanPassiveTotalPerChannel 200 +#define dot11OBSSScanActiveTotalPerChannel 20 +#define dot11BSSWidthTriggerScanInterval 300 /* Unit: sec */ +#define dot11BSSWidthChannelTransitionDelayFactor 5 +#define dot11OBSSScanActivityThreshold 25 + +#define OBSS_20_40M_TIMEOUT (dot11BSSWidthTriggerScanInterval + 10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Control MAC PCO function */ +typedef enum _ENUM_SYS_PCO_PHASE_T { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +} ENUM_SYS_PCO_PHASE_T, *P_ENUM_SYS_PCO_PHASE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +rlmObssInit ( + P_ADAPTER_T prAdapter + ); + +VOID +rlmObssScanDone ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ); + +VOID +rlmObssTriggerScan ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_OBSS_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h new file mode 100755 index 000000000000..6025b9044740 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h @@ -0,0 +1,126 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_protection.h#1 $ +*/ + +/*! \file "rlm_protection.h" + \brief +*/ + + + +/* +** $Log: rlm_protection.h $ + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +#ifndef _RLM_PROTECTION_H +#define _RLM_PROTECTION_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SYS_PROTECT_MODE_T { + SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ + SYS_PROTECT_MODE_ERP, /* Mode 1 */ + SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ + SYS_PROTECT_MODE_20M, /* Mode 3 */ + + SYS_PROTECT_MODE_NUM +} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; + +/* This definition follows HT Protection field of HT Operation IE */ +typedef enum _ENUM_HT_PROTECT_MODE_T { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; + + +typedef enum _ENUM_GF_MODE_T { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; + +typedef enum _ENUM_RIFS_MODE_T { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_PROTECTION_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h new file mode 100755 index 000000000000..2a744f7e3c68 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h @@ -0,0 +1,209 @@ +/* +** $Id: +*/ + +/*! \file "roaming_fsm.h" + \brief This file defines the FSM for Roaming MODULE. + + This file defines the FSM for Roaming MODULE. +*/ + + + +/* +** $Log: roaming_fsm.h $ + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * +*/ + +#ifndef _ROAMING_FSM_H +#define _ROAMING_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Roaming Discovery interval, SCAN result need to be updated */ +#define ROAMING_DISCOVERY_TIMEOUT_SEC 5 // Seconds. + +//#define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_ROAMING_FAIL_REASON_T { + ROAMING_FAIL_REASON_CONNLIMIT = 0, + ROAMING_FAIL_REASON_NOCANDIDATE, + ROAMING_FAIL_REASON_NUM +} ENUM_ROAMING_FAIL_REASON_T; + +/* events of roaming between driver and firmware */ +typedef enum _ENUM_ROAMING_EVENT_T { + ROAMING_EVENT_START = 0, + ROAMING_EVENT_DISCOVERY, + ROAMING_EVENT_ROAM, + ROAMING_EVENT_FAIL, + ROAMING_EVENT_ABORT, + ROAMING_EVENT_NUM +} ENUM_ROAMING_EVENT_T; + +typedef struct _ROAMING_PARAM_T { + UINT_16 u2Event; + UINT_16 u2Data; +} ROAMING_PARAM_T, *P_ROAMING_PARAM_T; + +/**/ +typedef enum _ENUM_ROAMING_STATE_T { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_ROAM, + ROAMING_STATE_NUM +} ENUM_ROAMING_STATE_T; + +typedef struct _ROAMING_INFO_T { + BOOLEAN fgIsEnableRoaming; + + ENUM_ROAMING_STATE_T eCurrentState; + + OS_SYSTIME rRoamingDiscoveryUpdateTime; + +} ROAMING_INFO_T, *P_ROAMING_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if CFG_SUPPORT_ROAMING +#define IS_ROAMING_ACTIVE(prAdapter) \ + (prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_ROAM) +#else +#define IS_ROAMING_ACTIVE(prAdapter) FALSE +#endif /* CFG_SUPPORT_ROAMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +roamingFsmInit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +roamingFsmUninit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +roamingFsmSendCmd ( + IN P_ADAPTER_T prAdapter, + IN P_ROAMING_PARAM_T prParam + ); + +VOID +roamingFsmScanResultsUpdate ( + IN P_ADAPTER_T prAdapter + ); + +VOID +roamingFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN ENUM_ROAMING_STATE_T eNextState + ); + +VOID +roamingFsmRunEventStart ( + IN P_ADAPTER_T prAdapter + ); + +VOID +roamingFsmRunEventDiscovery ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ); + +VOID +roamingFsmRunEventRoam ( + IN P_ADAPTER_T prAdapter + ); + +VOID +roamingFsmRunEventFail ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Reason + ); + +VOID +roamingFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +roamingFsmProcessEvent ( + IN P_ADAPTER_T prAdapter, + IN P_ROAMING_PARAM_T prParam + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ROAMING_FSM_H */ + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h new file mode 100755 index 000000000000..e18b201f14d9 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h @@ -0,0 +1,386 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rsn.h#1 $ +*/ + +/*! \file rsn.h + \brief The wpa/rsn related define, macro and structure are described here. +*/ + + + +/* +** $Log: rsn.h $ + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h and let the sw structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 wh.su + * NULL + * remove non-used code. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function prototype for generate wap/rsn ie + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function input parameter + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some event function declaration + * + * Nov 26 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * move the internal data structure for pmkid to rsn.h + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the port control and class error function + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the pmkid candidate + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +#ifndef _RSN_H +#define _RSN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* ----- Definitions for Cipher Suite Selectors ----- */ +#define RSN_CIPHER_SUITE_USE_GROUP_KEY 0x00AC0F00 +#define RSN_CIPHER_SUITE_WEP40 0x01AC0F00 +#define RSN_CIPHER_SUITE_TKIP 0x02AC0F00 +#define RSN_CIPHER_SUITE_CCMP 0x04AC0F00 +#define RSN_CIPHER_SUITE_WEP104 0x05AC0F00 +#if CFG_SUPPORT_802_11W +#define RSN_CIPHER_SUITE_AES_128_CMAC 0x06AC0F00 +#endif + +#define WPA_CIPHER_SUITE_NONE 0x00F25000 +#define WPA_CIPHER_SUITE_WEP40 0x01F25000 +#define WPA_CIPHER_SUITE_TKIP 0x02F25000 +#define WPA_CIPHER_SUITE_CCMP 0x04F25000 +#define WPA_CIPHER_SUITE_WEP104 0x05F25000 + +/* ----- Definitions for Authentication and Key Management Suite Selectors ----- */ +#define RSN_AKM_SUITE_NONE 0x00AC0F00 +#define RSN_AKM_SUITE_802_1X 0x01AC0F00 +#define RSN_AKM_SUITE_PSK 0x02AC0F00 +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 + +#define ELEM_ID_RSN_LEN_FIXED 20 /* The RSN IE len for associate request */ + +#define ELEM_ID_WPA_LEN_FIXED 22 /* The RSN IE len for associate request */ + +#define MASK_RSNIE_CAP_PREAUTH BIT(0) + +#define GET_SELECTOR_TYPE(x) ((UINT_8)(((x) >> 24) & 0x000000FF)) +#define SET_SELECTOR_TYPE(x, y) x = (((x) & 0x00FFFFFF) | (((UINT_32)(y) << 24) & 0xFF000000)) + +#define AUTH_CIPHER_CCMP 0x00000008 + +/* Cihpher suite flags */ +#define CIPHER_FLAG_NONE 0x00000000 +#define CIPHER_FLAG_WEP40 0x00000001 /* BIT 1 */ +#define CIPHER_FLAG_TKIP 0x00000002 /* BIT 2 */ +#define CIPHER_FLAG_CCMP 0x00000008 /* BIT 4 */ +#define CIPHER_FLAG_WEP104 0x00000010 /* BIT 5 */ +#define CIPHER_FLAG_WEP128 0x00000020 /* BIT 6 */ + +#define WAIT_TIME_IND_PMKID_CANDICATE_SEC 6 /* seconds */ +#define TKIP_COUNTERMEASURE_SEC 60 /* seconds */ + +#if CFG_SUPPORT_802_11W +#define RSN_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define RSN_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define RSN_AUTH_MFP_REQUIRED 2 /* MFP required */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Flags for PMKID Candidate list structure */ +#define EVENT_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + + +#define CONTROL_FLAG_UC_MGMT_NO_ENC BIT(5) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RSN_IE(fp) ((P_RSN_INFO_ELEM_T) fp) +#define WPA_IE(fp) ((P_WPA_INFO_ELEM_T) fp) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +BOOLEAN +rsnParseRsnIE( + IN P_ADAPTER_T prAdapter, + IN P_RSN_INFO_ELEM_T prInfoElem, + OUT P_RSN_INFO_T prRsnInfo + ); + +BOOLEAN +rsnParseWpaIE( + IN P_ADAPTER_T prAdapter, + IN P_WPA_INFO_ELEM_T prInfoElem, + OUT P_RSN_INFO_T prWpaInfo + ); + +BOOLEAN +rsnSearchSupportedCipher( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Cipher, + OUT PUINT_32 pu4Index + ); + +BOOLEAN +rsnSearchAKMSuite( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4AkmSuite, + OUT PUINT_32 pu4Index + ); + +BOOLEAN +rsnPerformPolicySelection( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ); + +VOID +rsnGenerateWpaNoneIE( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +rsnGenerateWPAIE( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +rsnGenerateRSNIE( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +BOOLEAN +rsnParseCheckForWFAInfoElem( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, + OUT PUINT_8 pucOuiType, + OUT PUINT_16 pu2SubTypeVersion + ); + +BOOLEAN +rsnIsSuitableBSS ( + IN P_ADAPTER_T prAdapter, + IN P_RSN_INFO_T prBssRsnInfo + ); + +#if CFG_SUPPORT_AAA +void +rsnParserCheckForRSNCCMPPSK ( + P_ADAPTER_T prAdapter, + P_RSN_INFO_ELEM_T prIe, + PUINT_16 pu2StatusCode + ); +#endif + +VOID +rsnTkipHandleMICFailure( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + IN BOOLEAN fgErrorKeyType + ); + +VOID +rsnSelectPmkidCandidateList( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +VOID +rsnUpdatePmkidCandidateList( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +BOOLEAN +rsnSearchPmkidEntry( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBssid, + OUT PUINT_32 pu4EntryIndex + ); + +BOOLEAN +rsnCheckPmkidCandicate( + IN P_ADAPTER_T prAdapter + ); + +VOID +rsnCheckPmkidCache( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ); + +VOID +rsnGeneratePmkidIndication( + IN P_ADAPTER_T prAdapter + ); + +VOID +rsnIndicatePmkidCand( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ); +#if CFG_SUPPORT_WPS2 +VOID +rsnGenerateWSCIE( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); +#endif + +#if CFG_SUPPORT_802_11W +UINT_32 +rsnCheckBipKeyInstalled( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +UINT_8 +rsnCheckSaQueryTimeout( + IN P_ADAPTER_T prAdapter + ); + +void +rsnStartSaQueryTimer( + IN P_ADAPTER_T prAdapter + ); + +void +rsnStartSaQuery( + IN P_ADAPTER_T prAdapter + ); + +void +rsnStopSaQuery( + IN P_ADAPTER_T prAdapter + ); + +void +rsnSaQueryRequest( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +void +rsnSaQueryAction( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +BOOLEAN +rsnCheckRxMgmt( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 ucSubtype + ); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RSN_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h new file mode 100755 index 000000000000..85ab71281b58 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h @@ -0,0 +1,847 @@ +/* +** $Id: @(#) +*/ + +/*! \file "scan.h" + \brief + +*/ + + + +/* +** $Log: scan.h $ + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module with structure miss-align pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix compile error. + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 12 2010 yuche.tsai + * NULL + * Add a functio prototype to find p2p descriptor of a bss descriptor directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Add function prototype for return channel. + * modify data structure for scan specific device ID or TYPE. (Move from P2P Connection Settings to Scan Param) + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Add a option for channel time extention in scan abort command. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Scan status "FIND" is used for P2P FSM find state. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related field in SCAN_PARAM_T. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * + * Add new HW CH macro support + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify scanBuildProbeReqFrameCommonIEs() to support P2P SCAN + * + * 02 23 2010 wh.su + * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver + * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Simplify the process of Beacon during SCAN and remove redundant variable in PRE_BSS_DESC_T + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding variable for wapi ap + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove non-used secuirty variavle + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Refine data structure of BSS_DESC_T and PRE_BSS_DESC_T + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add eNetType to rScanParam and revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add ucAvailablePhyTypeSet to BSS_DESC_T + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aucSrcAddress to SCAN_PARAM_T for P2P's Device Address + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security related variable + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security ie filed for scan parsing + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scanSearchBssDescByPolicy() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function declarations of scan_fsm.c + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scan.h to source control +** +*/ + +#ifndef _SCAN_H +#define _SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! Maximum buffer size of SCAN list */ +#define SCN_MAX_BUFFER_SIZE (CFG_MAX_NUM_BSS_LIST * ALIGN_4(sizeof(BSS_DESC_T))) + +#define SCN_RM_POLICY_EXCLUDE_CONNECTED BIT(0) // Remove SCAN result except the connected one. +#define SCN_RM_POLICY_TIMEOUT BIT(1) // Remove the timeout one +#define SCN_RM_POLICY_OLDEST_HIDDEN BIT(2) // Remove the oldest one with hidden ssid +#define SCN_RM_POLICY_SMART_WEAKEST BIT(3) /* If there are more than half BSS which has the + * same ssid as connection setting, remove the weakest one from them + * Else remove the weakest one. + */ +#define SCN_RM_POLICY_ENTIRE BIT(4) // Remove entire SCAN result + +#define SCN_BSS_DESC_SAME_SSID_THRESHOLD 3 /* This is used by POLICY SMART WEAKEST, + * If exceed this value, remove weakest BSS_DESC_T + * with same SSID first in large network. + */ + +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 5 // Second. + /* This is used by POLICY TIMEOUT, + * If exceed this value, remove timeout BSS_DESC_T. + */ + + + + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 // Second. + +/*----------------------------------------------------------------------------*/ +/* MSG_SCN_SCAN_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_REQ_SSID_WILDCARD BIT(0) +#define SCAN_REQ_SSID_P2P_WILDCARD BIT(1) +#define SCAN_REQ_SSID_SPECIFIED BIT(2) + + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM 4 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SCAN_TYPE_T { + SCAN_TYPE_PASSIVE_SCAN = 0, + SCAN_TYPE_ACTIVE_SCAN, + SCAN_TYPE_NUM +} ENUM_SCAN_TYPE_T, *P_ENUM_SCAN_TYPE_T; + +typedef enum _ENUM_SCAN_STATE_T { + SCAN_STATE_IDLE = 0, + SCAN_STATE_SCANNING, + SCAN_STATE_NUM +} ENUM_SCAN_STATE_T; + +typedef enum _ENUM_SCAN_CHANNEL_T { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +} ENUM_SCAN_CHANNEL, *P_ENUM_SCAN_CHANNEL; + +typedef struct _MSG_SCN_FSM_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4Dummy; +} MSG_SCN_FSM_T, *P_MSG_SCN_FSM_T; + + + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct _BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ + + BOOLEAN fgIsConnecting; /* If we are going to connect to this BSS + * (JOIN or ROAMING to another BSS), don't + * remove this record from BSS List. + */ + BOOLEAN fgIsConnected; /* If we have connected to this BSS (NORMAL_TR), + * don't removed this record from BSS list. + */ + + BOOLEAN fgIsHiddenSSID; /* When this flag is TRUE, means the SSID + * of this BSS is not known yet. + */ + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + + OS_SYSTIME rUpdateTime; + + ENUM_BSS_TYPE_T eBSSType; + + UINT_16 u2CapInfo; + + UINT_16 u2BeaconInterval; + UINT_16 u2ATIMWindow; + + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + BOOLEAN fgIsERPPresent; + BOOLEAN fgIsHTPresent; + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + + UINT_8 ucChannelNum; + + ENUM_CHNL_EXT_T eSco; /* Record bandwidth for association process + Some AP will send association resp by 40MHz BW */ + ENUM_BAND_T eBand; + + UINT_8 ucDTIMPeriod; + + BOOLEAN fgIsLargerTSF; /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ + + UINT_8 ucRCPI; + + UINT_8 ucWmmFlag; /* A flag to indicate this BSS's WMM capability */ + + /*! \brief The srbiter Search State will matched the scan result, + and saved the selected cipher and akm, and report the score, + for arbiter join state, join module will carry this target BSS + to rsn generate ie function, for gen wpa/rsn ie */ + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + + UINT_16 u2RsnCap; + + RSN_INFO_T rRSNInfo; + RSN_INFO_T rWPAInfo; +#if 1//CFG_SUPPORT_WAPI + WAPI_INFO_T rIEWAPI; + BOOL fgIEWAPI; +#endif + BOOL fgIERSN; + BOOL fgIEWPA; + + /*! \brief RSN parameters selected for connection */ + /*! \brief The Select score for final AP selection, + 0, no sec, 1,2,3 group cipher is WEP, TKIP, CCMP */ + UINT_8 ucEncLevel; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PPresent; + P_P2P_DEVICE_DESC_T prP2pDesc; + + UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ +// UINT_8 ucDevCapabilityBitmap; /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ +// UINT_8 ucGroupCapabilityBitmap; /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + + LINK_T rP2pDeviceList; + +// P_LINK_T prP2pDeviceList; + + /* For + * 1. P2P Capability. + * 2. P2P Device ID. ( in aucSrcAddr[] ) + * 3. NOA (TODO:) + * 4. Extend Listen Timing. (Probe Rsp) (TODO:) + * 5. P2P Device Info. (Probe Rsp) + * 6. P2P Group Info. (Probe Rsp) + */ +#endif + + BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ + UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ + + ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + + UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; +}; + + +typedef struct _SCAN_PARAM_T { /* Used by SCAN FSM */ + /* Active or Passive */ + ENUM_SCAN_TYPE_T eScanType; + + /* Network Type */ + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + + /* Specified SSID Type */ + UINT_8 ucSSIDType; + UINT_8 ucSSIDNum; + + /* Length of Specified SSID */ + UINT_8 ucSpecifiedSSIDLen[SCN_SSID_MAX_NUM]; + + /* Specified SSID */ + UINT_8 aucSpecifiedSSID[SCN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgFindSpecificDev; /* P2P: Discovery Protocol */ + UINT_8 aucDiscoverDevAddr[MAC_ADDR_LEN]; + BOOLEAN fgIsDevType; + P2P_DEVICE_TYPE_T rDiscoverDevType; + + UINT_16 u2PassiveListenInterval; + // TODO: Find Specific Device Type. +#endif /* CFG_SUPPORT_P2P */ + + BOOLEAN fgIsObssScan; + BOOLEAN fgIsScanV2; + + /* Run time flags */ + UINT_16 u2ProbeDelayTime; + + /* channel information */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + /* Feedback information */ + UINT_8 ucSeqNum; + + /* Information Element */ + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; + +} SCAN_PARAM_T, *P_SCAN_PARAM_T; + +typedef struct _SCAN_INFO_T { + ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ + + OS_SYSTIME rLastScanCompletedTime; + + SCAN_PARAM_T rScanParam; + + UINT_32 u4NumOfBssDesc; + + UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + LINK_T rBSSDescList; + + LINK_T rFreeBSSDescList; + + LINK_T rPendingMsgList; + + /* Sparse Channel Detection */ + BOOLEAN fgIsSparseChannelValid; + RF_CHANNEL_INFO_T rSparseChannel; + +} SCAN_INFO_T, *P_SCAN_INFO_T; + + +/* Incoming Mailbox Messages */ +typedef struct _MSG_SCN_SCAN_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_TYPE_T eScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucSSID[PARAM_MAX_LEN_SSID]; +#if CFG_ENABLE_WIFI_DIRECT + UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ +#endif + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} MSG_SCN_SCAN_REQ, *P_MSG_SCN_SCAN_REQ; + +typedef struct _MSG_SCN_SCAN_REQ_V2_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_TYPE_T eScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDNum; + P_PARAM_SSID_T prSsid; + UINT_16 u2ProbeDelay; + UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} MSG_SCN_SCAN_REQ_V2, *P_MSG_SCN_SCAN_REQ_V2; + + +typedef struct _MSG_SCN_SCAN_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsChannelExt; +#endif +} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; + +/* Outgoing Mailbox Messages */ +typedef enum _ENUM_SCAN_STATUS_T { + SCAN_STATUS_DONE = 0, + SCAN_STATUS_CANCELLED, + SCAN_STATUS_FAIL, + SCAN_STATUS_BUSY, + SCAN_STATUS_NUM +} ENUM_SCAN_STATUS, *P_ENUM_SCAN_STATUS; + +typedef struct _MSG_SCN_SCAN_DONE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_STATUS eScanStatus; +} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in scan.c */ +/*----------------------------------------------------------------------------*/ +VOID +scnInit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +scnUninit ( + IN P_ADAPTER_T prAdapter + ); + +/* BSS-DESC Search */ +P_BSS_DESC_T +scanSearchBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ); + +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ); + +P_BSS_DESC_T +scanSearchBssDescByTA ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[] + ); + +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ); + + +/* BSS-DESC Search - Alternative */ +P_BSS_DESC_T +scanSearchExistingBssDesc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[] + ); + +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ); + + +/* BSS-DESC Allocation */ +P_BSS_DESC_T +scanAllocateBssDesc ( + IN P_ADAPTER_T prAdapter + ); + +/* BSS-DESC Removal */ +VOID +scanRemoveBssDescsByPolicy ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4RemovePolicy + ); + +VOID +scanRemoveBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ); + +VOID +scanRemoveBssDescByBandAndNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +/* BSS-DESC State Change */ +VOID +scanRemoveConnFlagOfBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ); + +#if 0 +/* BSS-DESC Insertion */ +P_BSS_DESC_T +scanAddToInternalScanResult ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSWRfb, + IN P_BSS_DESC_T prBssDesc + ); +#endif + +/* BSS-DESC Insertion - ALTERNATIVE */ +P_BSS_DESC_T +scanAddToBssDesc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +WLAN_STATUS +scanProcessBeaconAndProbeResp ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSWRfb + ); + +VOID +scanBuildProbeReqFrameCommonIEs ( + IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucDesiredSsid, + IN UINT_32 u4DesiredSsidLen, + IN UINT_16 u2SupportedRateSet + ); + +WLAN_STATUS +scanSendProbeReqFrames ( + IN P_ADAPTER_T prAdapter, + IN P_SCAN_PARAM_T prScanParam + ); + +VOID +scanUpdateBssDescForSearch ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ); + +P_BSS_DESC_T +scanSearchBssDescByPolicy ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +WLAN_STATUS +scanAddScanResult ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_SW_RFB_T prSwRfb + ); + +/*----------------------------------------------------------------------------*/ +/* Routines in scan_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN ENUM_SCAN_STATE_T eNextState + ); + +/*----------------------------------------------------------------------------*/ +/* Command Routines */ +/*----------------------------------------------------------------------------*/ +VOID +scnSendScanReq ( + IN P_ADAPTER_T prAdapter + ); + +VOID +scnSendScanReqV2 ( + IN P_ADAPTER_T prAdapter + ); + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID +scnEventScanDone( + IN P_ADAPTER_T prAdapter, + IN P_EVENT_SCAN_DONE prScanDone + ); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmMsgStart ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +scnFsmMsgAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +scnFsmHandleScanMsg ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_SCN_SCAN_REQ prScanReqMsg + ); + +VOID +scnFsmHandleScanMsgV2 ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg + ); + +VOID +scnFsmRemovePendingMsg ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, + IN UINT_8 ucNetTypeIndex + ); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, + IN UINT_8 ucNetTypeIndex, + IN ENUM_SCAN_STATUS eScanStatus + ); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnQuerySparseChannel ( + IN P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prSparseBand, + PUINT_8 pucSparseChannel + ); + + +#endif /* _SCAN_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h new file mode 100755 index 000000000000..17c651937abc --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h @@ -0,0 +1,284 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/sec_fsm.h#1 $ +*/ + +/*! \file sec_fsm.h + \brief Declaration of functions and finite state machine for SECURITY Module. + + Function declaration for privacy.c and SEC_STATE for SECURITY FSM. +*/ + + + +/* +** $Log: sec_fsm.h $ + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 03 04 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Code refine, and remove non-used code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * fixed the deauth Tx done callback parameter + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the reference function declaration + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * delete non-used code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function prototype + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function declaration + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security variable + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** \main\maintrunk.MT5921\14 2009-04-06 15:35:47 GMT mtk01088 +** add the variable to set the disable AP selection for privacy check, for wps open networking. +** \main\maintrunk.MT5921\13 2008-11-19 11:46:01 GMT mtk01088 +** rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\12 2008-08-28 20:37:11 GMT mtk01088 +** remove non-used code +** +** \main\maintrunk.MT5921\11 2008-03-18 09:51:52 GMT mtk01088 +** Add function declaration for timer to indicate pmkid candidate +** \main\maintrunk.MT5921\10 2008-02-29 15:12:08 GMT mtk01088 +** add variable for sw port control +** \main\maintrunk.MT5921\9 2008-02-29 12:37:30 GMT mtk01088 +** rename the security related function declaration +** \main\maintrunk.MT5921\8 2007-12-27 13:59:08 GMT mtk01088 +** adjust the wlan table and sec fsm init timing +** \main\maintrunk.MT5921\7 2007-11-20 10:39:49 GMT mtk01088 +** add function timer for wait EAPoL Error timeout +** \main\maintrunk.MT5921\6 2007-11-06 20:39:08 GMT mtk01088 +** rename the counter measure timer +** \main\maintrunk.MT5921\5 2007-11-06 20:14:31 GMT mtk01088 +** add a abort function +** Revision 1.5 2007/07/16 02:33:42 MTK01088 +** change the ENUM declaration structure prefix from r to e +** +** Revision 1.4 2007/07/09 06:23:10 MTK01088 +** update +** +** Revision 1.3 2007/07/04 10:09:04 MTK01088 +** adjust the state for security fsm +** change function name +** +** Revision 1.2 2007/07/03 08:13:22 MTK01088 +** change the sec fsm state +** add the event for sec fsm +** +** Revision 1.1 2007/06/27 06:20:35 MTK01088 +** add the sec fsm header file +** +** +*/ +#ifndef _SEC_FSM_H +#define _SEC_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* TKIP CounterMeasure interval for Rejoin to Network. */ +#define COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC 60 + +/* Timeout to wait the EAPoL Error Report frame Send out. */ +#define EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef UINT_32 SEC_STATUS, *P_SEC_STATUS; + +#if 0 +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; /* MAC address */ + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; +#endif + +typedef SEC_STATUS (*PFN_SEC_FSM_STATE_HANDLER)(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SEC_STATE_TRANSITION_FLAG fgIsTransition +#define SEC_NEXT_STATE_VAR eNextState + +#define SEC_STATE_TRANSITION(prAdapter, prSta, eFromState, eToState) \ + { secFsmTrans_ ## eFromState ## _to_ ## eToState(prAdapter, prSta); \ + SEC_NEXT_STATE_VAR = SEC_STATE_ ## eToState; \ + SEC_STATE_TRANSITION_FLAG = (BOOLEAN)TRUE; \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle the sec check */ +/*--------------------------------------------------------------*/ +/***** Routines in sec_fsm.c *****/ +VOID +secFsmInit( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEventInit( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEventStart( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEventAbort( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +BOOLEAN +secFsmEventPTKInstalled( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEvent2ndEapolTx( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEvent4ndEapolTxDone( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEventEapolTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +VOID +secFsmEventEapolTxTimeout ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ); + +VOID +secFsmEventDeauthTxDone( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +VOID +secFsmEventStartCounterMeasure( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ); + +VOID +secFsmEventEndOfCounterMeasure( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _SEC_FSM_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h new file mode 100755 index 000000000000..4ea322d9763d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h @@ -0,0 +1,180 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 $ +*/ + +/*! \file "swcr.h" + \brief +*/ + + + +/* + * + */ + +#ifndef _SWCR_H +#define _SWCR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define SWCR_VAR(x) ((VOID *)&x) +#define SWCR_FUNC(x) ((VOID *)x) + +#define SWCR_T_FUNC BIT(7) + +#define SWCR_L_32 3 +#define SWCR_L_16 2 +#define SWCR_L_8 1 + +#define SWCR_READ 0 +#define SWCR_WRITE 1 + +#define SWCR_MAP_NUM(x) (sizeof(x)/sizeof(x[0])) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action,rw,index) \ + index = action & 0x7F; \ + rw = action >> 7; + + +extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ + +typedef VOID (*PFN_SWCR_RW_T)(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +typedef VOID (*PFN_CMD_RW_T)(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); + +typedef struct _SWCR_MAP_ENTRY_T { + UINT_16 u2Type; + PVOID u4Addr; +} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; + + +typedef struct _SWCR_MOD_MAP_ENTRY_T { + UINT_8 ucMapNum; + P_SWCR_MAP_ENTRY_T prSwCrMap; +} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; + +typedef enum _ENUM_SWCR_DBG_TYPE_T { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +} ENUM_SWCR_DBG_TYPE_T; + +typedef enum _ENUM_SWCR_DBG_ALL_T { + SWCR_DBG_ALL_TX_CNT = 0, + SWCR_DBG_ALL_TX_BCN_CNT, + SWCR_DBG_ALL_TX_FAILED_CNT, + SWCR_DBG_ALL_TX_RETRY_CNT, + SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, + SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, + SWCR_DBG_ALL_TX_MGNT_DROP_CNT, + SWCR_DBG_ALL_TX_ERROR_CNT, + + SWCR_DBG_ALL_RX_CNT, + SWCR_DBG_ALL_RX_DROP_CNT, + SWCR_DBG_ALL_RX_DUP_DROP_CNT, + SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_FCSERR_CNT, + SWCR_DBG_ALL_RX_FIFOFULL_CNT, + SWCR_DBG_ALL_RX_PFDROP_CNT, + + SWCR_DBG_ALL_PWR_PS_POLL_CNT, + SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, + SWCR_DBG_ALL_PWR_BCN_IND_CNT, + SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, + SWCR_DBG_ALL_PWR_PM_STATE0, + SWCR_DBG_ALL_PWR_PM_STATE1, + SWCR_DBG_ALL_PWR_CUR_PS_PROF0, + SWCR_DBG_ALL_PWR_CUR_PS_PROF1, + + SWCR_DBG_ALL_AR_STA0_RATE, + SWCR_DBG_ALL_AR_STA0_BWGI, + SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, + + SWCR_DBG_ALL_ROAMING_ENABLE, + SWCR_DBG_ALL_ROAMING_ROAM_CNT, + SWCR_DBG_ALL_ROAMING_INT_CNT, + + SWCR_DBG_ALL_BB_RX_MDRDY_CNT, + SWCR_DBG_ALL_BB_RX_FCSERR_CNT, + SWCR_DBG_ALL_BB_CCK_PD_CNT, + SWCR_DBG_ALL_BB_OFDM_PD_CNT, + SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, + SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, + + SWCR_DBG_ALL_NUM +} ENUM_SWCR_DBG_ALL_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID swCrReadWriteCmd( + P_ADAPTER_T prAdapter, + UINT_8 ucRead, + UINT_16 u2Addr, + UINT_32 *pu4Data + ); + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType); +VOID swCrDebugInit(P_ADAPTER_T prAdapter); +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout); +VOID swCrDebugUninit(P_ADAPTER_T prAdapter); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h new file mode 100755 index 000000000000..a47acae67778 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h @@ -0,0 +1,120 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wapi.h#1 $ +*/ + +/*! \file wapi.h + \brief The wapi related define, macro and structure are described here. +*/ + + + +/* +** $Log: wapi.h $ + * + * 07 20 2010 wh.su + * + * . + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the wapi function name and adding the generate wapi ie function + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some wapi structure define + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** \main\maintrunk.MT5921\1 2009-10-09 17:06:29 GMT mtk01088 +** +*/ + +#ifndef _WAPI_H +#define _WAPI_H + +#if CFG_SUPPORT_WAPI + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define WAPI_CIPHER_SUITE_WPI 0x01721400 /* WPI_SMS4 */ +#define WAPI_AKM_SUITE_802_1X 0x01721400 /* WAI */ +#define WAPI_AKM_SUITE_PSK 0x02721400 /* WAI_PSK */ + +#define ELEM_ID_WAPI 68 /* WAPI IE */ + +#define WAPI_IE(fp) ((P_WAPI_INFO_ELEM_T) fp) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +wapiGenerateWAPIIE( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +BOOLEAN +wapiParseWapiIE ( + IN P_WAPI_INFO_ELEM_T prInfoElem, + OUT P_WAPI_INFO_T prWapiInfo + ); + +BOOLEAN +wapiPerformPolicySelection( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ); + +//BOOLEAN +//wapiUpdateTxKeyIdx ( +// IN P_STA_RECORD_T prStaRec, +// IN UINT_8 ucWlanIdx +// ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif +#endif /* _WAPI_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h new file mode 100755 index 000000000000..2680a88eb9a2 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h @@ -0,0 +1,86 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wlan_typedef.h#1 $ +*/ + +/*! \file wlan_typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to all MGMT Protocol Stack. +*/ + + + +/* +** $Log: wlan_typedef.h $ +*/ + +#ifndef _WLAN_TYPEDEF_H +#define _WLAN_TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for BSS_INFO_T structure, to describe the attributes used in a + * common BSS. + */ +typedef struct _BSS_INFO_T BSS_INFO_T, *P_BSS_INFO_T; + +typedef BSS_INFO_T AIS_BSS_INFO_T, *P_AIS_BSS_INFO_T; +typedef BSS_INFO_T P2P_BSS_INFO_T, *P_P2P_BSS_INFO_T; +typedef BSS_INFO_T BOW_BSS_INFO_T, *P_BOW_BSS_INFO_T; + +typedef struct _AIS_SPECIFIC_BSS_INFO_T AIS_SPECIFIC_BSS_INFO_T, *P_AIS_SPECIFIC_BSS_INFO_T; +typedef struct _P2P_SPECIFIC_BSS_INFO_T P2P_SPECIFIC_BSS_INFO_T, *P_P2P_SPECIFIC_BSS_INFO_T; +typedef struct _BOW_SPECIFIC_BSS_INFO_T BOW_SPECIFIC_BSS_INFO_T, *P_BOW_SPECIFIC_BSS_INFO_T; +/* CFG_SUPPORT_WFD */ +typedef struct _WFD_CFG_SETTINGS_T WFD_CFG_SETTINGS_T, *P_WFD_CFG_SETTINGS_T; + + +/* BSS related structures */ +/* Type definition for BSS_DESC_T structure, to describe parameter sets of a particular BSS */ +typedef struct _BSS_DESC_T BSS_DESC_T, *P_BSS_DESC_T, **PP_BSS_DESC_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _WLAN_TYPEDEF_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h new file mode 100755 index 000000000000..ac54cbc86dfa --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h @@ -0,0 +1,100 @@ +/* +** $Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/include/mgmt/wnm.h#1 $ +*/ + +/*! \file wnm.h + \brief This file contains the IEEE 802.11 family related 802.11v network management + for MediaTek 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wnm.h $ + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * +*/ + +#ifndef _WNM_H +#define _WNM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _TIMINGMSMT_PARAM_T { + BOOLEAN fgInitiator; + UINT_8 ucTrigger; + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ + UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ + UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ +} TIMINGMSMT_PARAM_T, *P_TIMINGMSMT_PARAM_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +wnmWNMAction ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +wnmReportTimingMeas ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIndex, + IN UINT_32 u4ToD, + IN UINT_32 u4ToA + ); + +#define WNM_UNIT_TEST 1 + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WNM_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h new file mode 100755 index 000000000000..098c30acf0ec --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h @@ -0,0 +1,1413 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/adapter.h#3 $ +*/ + +/*! \file adapter.h + \brief Definition of internal data structure for driver manipulation. + + In this file we define the internal data structure - ADAPTER_T which stands + for MiniPort ADAPTER(From Windows point of view) or stands for Network ADAPTER. +*/ + + + +/* +** $Log: adapter.h $ +** +** 11 15 2012 cp.wu +** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j +** do not try reconnecting when being disconnected by the peer +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve inorder issue under AP mode. + * + * data frame may TX before assoc response frame. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Remove ERP member in adapter structure + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * Action frame callback for GO Device Discoverability Req. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 yuche.tsai + * [WCXRP00000533] [Volunteer Patch][MT6620][Driver] Provide a P2P function API for Legacy WiFi to query AP mode. + * Provide an API for Legacy WiFi to query the operation mode.. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Chnage GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module with structure miss-align pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA module. + * Provide disconnect function for AAA module. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 george.huang + * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting + * Support CTIA power mode setting. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Add CWMin CWMax for AP to generate IE. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Add a common IE buffer in P2P INFO structure. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 cp.wu + * NULL + * restore configuration as before. + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 yuche.tsai + * NULL + * Add an intend mode for BSS info. + * It is used to let P2P BSS Info to know which OP Mode it is going to become. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 02 2010 cp.wu + * NULL + * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 yuche.tsai + * + * Remove BSS info which is redonedent in Wifi Var.. + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P FSM Info in adapter. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related field, additional include p2p_fsm.h if p2p is enabled. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 04 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * reserve field of privacy filter and RTS threshold setting. + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * 2) command sequence number is now increased atomically + * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move ucCmdSeqNum as instance variable + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * 4. correct some HAL implementation + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * and result is retrieved by get ATInfo instead + * * * 2) add 4 counter for recording aggregation statistics + * + * 12 28 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate redundant variables for connection_state +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-16 18:02:03 GMT mtk02752 +** add external reference to avoid compilation error +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:40:26 GMT mtk02752 +** eliminate unused member +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-08 17:36:08 GMT mtk02752 +** add RF test data members into P_ADAPTER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:45 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-28 10:29:57 GMT mtk01461 +** Add read WTSR for SDIO_STATUS_ENHANCE mode +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:37:35 GMT mtk01461 +** Add prPendingCmdInfoOfOID for temporarily saving the CMD_INFO_T before en-queue to rCmdQueue +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:57:51 GMT mtk01461 +** Add MGMT Buffer Info +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:34:12 GMT mtk01461 +** Add SW pre test CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:41:48 GMT mtk01461 +** Add fgIsWmmAssoc flag for TC assignment +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:51 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:51:52 GMT mtk01426 +** Add #if CFG_SDIO_RX_ENHANCE related data structure +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:17 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T SDIO_CTRL_T, *P_SDIO_CTRL_T; + +typedef struct _WLAN_INFO_T { + PARAM_BSSID_EX_T rCurrBssId; + + // Scan Result + PARAM_BSSID_EX_T arScanResult[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 apucScanResultIEs[CFG_MAX_NUM_BSS_LIST]; + UINT_32 u4ScanResultNum; + + // IE pool for Scanning Result + UINT_8 aucScanIEBuf[CFG_MAX_COMMON_IE_BUF_LEN]; + UINT_32 u4ScanIEBufferUsage; + + OS_SYSTIME u4SysTime; + + // connection parameter (for Ad-Hoc) + UINT_16 u2BeaconPeriod; + UINT_16 u2AtimWindow; + + PARAM_RATES eDesiredRates; + CMD_LINK_ATTRIB eLinkAttr; +// CMD_PS_PROFILE_T ePowerSaveMode; + CMD_PS_PROFILE_T arPowerSaveMode[NETWORK_TYPE_INDEX_NUM]; + + // trigger parameter + ENUM_RSSI_TRIGGER_TYPE eRssiTriggerType; + PARAM_RSSI rRssiTriggerValue; + + // Privacy Filter + ENUM_PARAM_PRIVACY_FILTER_T ePrivacyFilter; + + // RTS Threshold + PARAM_RTS_THRESHOLD eRtsThreshold; + + // Network Type + UINT_8 ucNetworkType; + + // Network Type In Use + UINT_8 ucNetworkTypeInUse; + +} WLAN_INFO_T, *P_WLAN_INFO_T; + +/* Session for CONNECTION SETTINGS */ +typedef struct _CONNECTION_SETTINGS_T { + + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + + UINT_8 ucDelayTimeOfDisconnectEvent; + + BOOLEAN fgIsConnByBssidIssued; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + + BOOLEAN fgIsConnReqIssued; + BOOLEAN fgIsDisconnectedByNonRequest; + + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + + ENUM_PARAM_OP_MODE_T eOPMode; + + ENUM_PARAM_CONNECTION_POLICY_T eConnectionPolicy; + + ENUM_PARAM_AD_HOC_MODE_T eAdHocMode; + + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + + BOOLEAN fgIsScanReqIssued; + + + /* MIB attributes */ + UINT_16 u2BeaconPeriod; + + UINT_16 u2RTSThreshold; /* User desired setting */ + + UINT_16 u2DesiredNonHTRateSet; /* User desired setting */ + + UINT_8 ucAdHocChannelNum; /* For AdHoc */ + + ENUM_BAND_T eAdHocBand; /* For AdHoc */ + + UINT_32 u4FreqInKHz; /* Center frequency */ + + /* ATIM windows using for IBSS power saving function */ + UINT_16 u2AtimWindow; + + /* Features */ + BOOLEAN fgIsEnableRoaming; + + BOOLEAN fgIsAdHocQoSEnable; + + ENUM_PARAM_PHY_CONFIG_T eDesiredPhyConfig; + + /* Used for AP mode for desired channel and bandwidth */ + UINT_16 u2CountryCode; + UINT_8 uc2G4BandwidthMode; /* 20/40M or 20M only */ + UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only */ + + BOOLEAN fgTxShortGIDisabled; + BOOLEAN fgRxShortGIDisabled; + +#if CFG_SUPPORT_802_11D + BOOLEAN fgMultiDomainCapabilityEnabled; +#endif /* CFG_SUPPORT_802_11D*/ + + +#if 1 //CFG_SUPPORT_WAPI + BOOL fgWapiMode; + UINT_32 u4WapiSelectedGroupCipher; + UINT_32 u4WapiSelectedPairwiseCipher; + UINT_32 u4WapiSelectedAKMSuite; +#endif + + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + BOOLEAN fgPrivacyCheckDisable; + + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 bmfgApsdEnAc; + + /* for RSN info store, when upper layer set rsn info */ + RSN_INFO_T rRsnInfo; + +} CONNECTION_SETTINGS_T, *P_CONNECTION_SETTINGS_T; + +struct _BSS_INFO_T { + + ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ + ENUM_PARAM_MEDIA_STATE_T eConnectionStateIndicated; /* The Media State that report to HOST */ + + ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ +#if CFG_ENABLE_WIFI_DIRECT + ENUM_OP_MODE_T eIntendOPMode; +#endif + + BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */ + + UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ + + UINT_8 ucReasonOfDisconnect; /* Used by media state indication */ + + UINT_8 ucSSIDLen; /* Length of SSID */ + +#if CFG_ENABLE_WIFI_DIRECT + ENUM_HIDDEN_SSID_TYPE_T eHiddenSsidType; /* For Hidden SSID usage. */ +#endif + + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID used in this BSS */ + + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* The BSSID of the associated BSS */ + + UINT_8 aucOwnMacAddr[MAC_ADDR_LEN];/* Owned MAC Address used in this BSS */ + + P_STA_RECORD_T prStaRecOfAP; /* For Infra Mode, and valid only if + * eConnectionState == MEDIA_STATE_CONNECTED + */ + LINK_T rStaRecOfClientList; /* For IBSS/AP Mode, all known STAs in current BSS */ + + UINT_16 u2CapInfo; /* Change Detection */ + + UINT_16 u2BeaconInterval; /* The Beacon Interval of this BSS */ + + + UINT_16 u2ATIMWindow; /* For IBSS Mode */ + + UINT_16 u2AssocId; /* For Infra Mode, it is the Assoc ID assigned by AP. + */ + + + UINT_8 ucDTIMPeriod; /* For Infra/AP Mode */ + + UINT_8 ucDTIMCount; /* For AP Mode, it is the DTIM value we should carried in + * the Beacon of next TBTT. + */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (This is deduced from received BSS_DESC_T) + */ + + UINT_8 ucNonHTBasicPhyType; /* The Basic PHY Type Index, used to setup Phy Capability */ + + UINT_8 ucConfigAdHocAPMode; /* The configuration of AdHoc/AP Mode. e.g. 11g or 11b */ + + UINT_8 ucBeaconTimeoutCount; /* For Infra/AP Mode, it is a threshold of Beacon Lost Count to + confirm connection was lost */ + + BOOLEAN fgHoldSameBssidForIBSS; /* For IBSS Mode, to keep use same BSSID to extend the life cycle of an IBSS */ + + BOOLEAN fgIsBeaconActivated; /* For AP/IBSS Mode, it is used to indicate that Beacon is sending */ + + P_MSDU_INFO_T prBeacon; /* For AP/IBSS Mode - Beacon Frame */ + + BOOLEAN fgIsIBSSMaster; /* For IBSS Mode - To indicate that we can reply ProbeResp Frame. + In current TBTT interval */ + + BOOLEAN fgIsShortPreambleAllowed; /* From Capability Info. of AssocResp Frame AND of Beacon/ProbeResp Frame */ + BOOLEAN fgUseShortPreamble; /* Short Preamble is enabled in current BSS. */ + BOOLEAN fgUseShortSlotTime; /* Short Slot Time is enabled in current BSS. */ + + UINT_16 u2OperationalRateSet; /* Operational Rate Set of current BSS */ + UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of current BSS */ + + + UINT_8 ucAllSupportedRatesLen; /* Used for composing Beacon Frame in AdHoc or AP Mode */ + UINT_8 aucAllSupportedRates[RATE_NUM]; + + UINT_8 ucAssocClientCnt; /* TODO(Kevin): Number of associated clients */ + + BOOLEAN fgIsProtection; + BOOLEAN fgIsQBSS; /* fgIsWmmBSS; */ /* For Infra/AP/IBSS Mode, it is used to indicate if we support WMM in + * current BSS. */ + BOOLEAN fgIsNetAbsent; /* TRUE: BSS is absent, FALSE: BSS is present */ + + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + UINT_16 u2RsnSelectedCapInfo; + + /*------------------------------------------------------------------------*/ + /* Power Management related information */ + /*------------------------------------------------------------------------*/ + PM_PROFILE_SETUP_INFO_T rPmProfSetupInfo; + + + /*------------------------------------------------------------------------*/ + /* WMM/QoS related information */ + /*------------------------------------------------------------------------*/ + UINT_8 ucWmmParamSetCount; /* Used to detect the change of EDCA parameters. For AP mode, the value is used in WMM IE */ + + AC_QUE_PARMS_T arACQueParms[WMM_AC_INDEX_NUM]; + + UINT_8 aucCWminLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWminLog2 */ + UINT_8 aucCWmaxLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWmaxLog2 */ + AC_QUE_PARMS_T arACQueParmsForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the value */ + + /*------------------------------------------------------------------------*/ + /* 802.11n HT operation IE when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT)*/ + /* is true. They have the same definition with fields of */ + /* information element (CM) */ + /*------------------------------------------------------------------------*/ + ENUM_BAND_T eBand; + UINT_8 ucPrimaryChannel; + UINT_8 ucHtOpInfo1; + UINT_16 u2HtOpInfo2; + UINT_16 u2HtOpInfo3; + + /*------------------------------------------------------------------------*/ + /* Required protection modes (CM) */ + /*------------------------------------------------------------------------*/ + BOOLEAN fgErpProtectMode; + ENUM_HT_PROTECT_MODE_T eHtProtectMode; + ENUM_GF_MODE_T eGfOperationMode; + ENUM_RIFS_MODE_T eRifsOperationMode; + + BOOLEAN fgObssErpProtectMode; /* GO only */ + ENUM_HT_PROTECT_MODE_T eObssHtProtectMode; /* GO only */ + ENUM_GF_MODE_T eObssGfOperationMode; /* GO only */ + BOOLEAN fgObssRifsOperationMode; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* OBSS to decide if 20/40M bandwidth is permitted. */ + /* The first member indicates the following channel list length. */ + /*------------------------------------------------------------------------*/ + BOOLEAN fgAssoc40mBwAllowed; + BOOLEAN fg40mBwAllowed; + ENUM_CHNL_EXT_T eBssSCO; /* Real setting for HW + * 20/40M AP mode will always set 40M, + * but its OP IE can be changed. + */ + UINT_8 auc2G_20mReqChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_NonHtChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_PriChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_SecChnlList[CHNL_LIST_SZ_2G + 1]; + + UINT_8 auc5G_20mReqChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_NonHtChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_PriChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_SecChnlList[CHNL_LIST_SZ_5G + 1]; + + TIMER_T rObssScanTimer; + UINT_16 u2ObssScanInterval; /* in unit of sec */ + + BOOLEAN fgObssActionForcedTo20M; /* GO only */ + BOOLEAN fgObssBeaconForcedTo20M; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*------------------------------------------------------------------------*/ + UINT_8 ucHwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ + UINT_16 u2HwLPWakeupGuardTimeUsec; + + + UINT_8 ucBssFreeQuota; /* The value is updated from FW */ +}; + + +struct _AIS_SPECIFIC_BSS_INFO_T { + UINT_8 ucRoamingAuthTypes; /* This value indicate the roaming type used in AIS_JOIN */ + + BOOLEAN fgIsIBSSActive; + + /*! \brief Global flag to let arbiter stay at standby and not connect to any network */ + BOOLEAN fgCounterMeasure; + UINT_8 ucWEPDefaultKeyID; + BOOLEAN fgTransmitKeyExist; /* Legacy wep Transmit key exist or not */ + + /* While Do CounterMeasure procedure, check the EAPoL Error report have send out */ + BOOLEAN fgCheckEAPoLTxDone; + + UINT_32 u4RsnaLastMICFailTime; + + /* Stored the current bss wpa rsn cap filed, used for roaming policy */ + //UINT_16 u2RsnCap; + TIMER_T rPreauthenticationTimer; + + /* By the flow chart of 802.11i, + wait 60 sec before associating to same AP + or roaming to a new AP + or sending data in IBSS, + keep a timer for handle the 60 sec counterMeasure */ + TIMER_T rRsnaBlockTrafficTimer; + TIMER_T rRsnaEAPoLReportTimeoutTimer; + + /* For Keep the Tx/Rx Mic key for TKIP SW Calculate Mic */ + /* This is only one for AIS/AP */ + UINT_8 aucTxMicKey[8]; + UINT_8 aucRxMicKey[8]; + + /* Buffer for WPA2 PMKID */ + /* The PMKID cache lifetime is expire by media_disconnect_indication */ + UINT_32 u4PmkidCandicateCount; + PMKID_CANDICATE_T arPmkidCandicate[CFG_MAX_PMKID_CACHE]; + UINT_32 u4PmkidCacheCount; + PMKID_ENTRY_T arPmkidCache[CFG_MAX_PMKID_CACHE]; + BOOLEAN fgIndicatePMKID; +#if CFG_SUPPORT_802_11W + BOOLEAN fgMgmtProtection; + UINT_32 u4SaQueryStart; + UINT_32 u4SaQueryCount; + UINT_8 ucSaQueryTimedOut; + PUINT_8 pucSaQueryTransId; + TIMER_T rSaQueryTimer; + BOOLEAN fgBipKeyInstalled; +#endif +}; + +struct _BOW_SPECIFIC_BSS_INFO_T { + UINT_16 u2Reserved; /* Reserved for Data Type Check */ +}; + +#if CFG_SLT_SUPPORT +typedef struct _SLT_INFO_T { + + P_BSS_DESC_T prPseudoBssDesc; + UINT_16 u2SiteID; + UINT_8 ucChannel2G4; + UINT_8 ucChannel5G; + BOOLEAN fgIsDUT; + UINT_32 u4BeaconReceiveCnt; + /////////Deprecated///////// + P_STA_RECORD_T prPseudoStaRec; +} SLT_INFO_T, *P_SLT_INFO_T; +#endif + + +/* Major member variables for WiFi FW operation. + Variables within this region will be ready for access after WIFI function is enabled. +*/ +typedef struct _WIFI_VAR_T { + BOOLEAN fgIsRadioOff; + + BOOLEAN fgIsEnterD3ReqIssued; + + BOOLEAN fgDebugCmdResp; + + CONNECTION_SETTINGS_T rConnSettings; + + SCAN_INFO_T rScanInfo; + +#if CFG_SUPPORT_ROAMING + ROAMING_INFO_T rRoamingInfo; +#endif /* CFG_SUPPORT_ROAMING */ + + AIS_FSM_INFO_T rAisFsmInfo; + + ENUM_PWR_STATE_T aePwrState[NETWORK_TYPE_INDEX_NUM]; + + BSS_INFO_T arBssInfo[NETWORK_TYPE_INDEX_NUM]; + + AIS_SPECIFIC_BSS_INFO_T rAisSpecificBssInfo; + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings; + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + P_P2P_FSM_INFO_T prP2pFsmInfo; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + BOW_SPECIFIC_BSS_INFO_T rBowSpecificBssInfo; + BOW_FSM_INFO_T rBowFsmInfo; +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + DEAUTH_INFO_T arDeauthInfo[MAX_DEAUTH_INFO_COUNT]; + + /* Current Wi-Fi Settings and Flags */ + UINT_8 aucPermanentAddress[MAC_ADDR_LEN]; + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + UINT_8 aucDeviceAddress[MAC_ADDR_LEN]; + UINT_8 aucInterfaceAddress[MAC_ADDR_LEN]; + + UINT_8 ucAvailablePhyTypeSet; + + ENUM_PHY_TYPE_INDEX_T eNonHTBasicPhyType2G4; /* Basic Phy Type used by SCN according + * to the set of Available PHY Types + */ + + ENUM_PARAM_PREAMBLE_TYPE_T ePreambleType; + ENUM_REGISTRY_FIXED_RATE_T eRateSetting; + + BOOLEAN fgIsShortSlotTimeOptionEnable; + /* User desired setting, but will honor the capability of AP */ + + BOOLEAN fgEnableJoinToHiddenSSID; + BOOLEAN fgSupportWZCDisassociation; + + BOOLEAN fgSupportQoS; + BOOLEAN fgSupportAmpduTx; + BOOLEAN fgSupportAmpduRx; + BOOLEAN fgSupportTspec; + BOOLEAN fgSupportUAPSD; + BOOLEAN fgSupportULPSMP; + +#if CFG_SLT_SUPPORT + SLT_INFO_T rSltInfo; +#endif + +} WIFI_VAR_T, *P_WIFI_VAR_T;/* end of _WIFI_VAR_T */ + +/* cnm_timer module */ +typedef struct { + LINK_T rLinkHead; + OS_SYSTIME rNextExpiredSysTime; + KAL_WAKE_LOCK_T rWakeLock; + BOOLEAN fgWakeLocked; +} ROOT_TIMER, *P_ROOT_TIMER; + + +/* FW/DRV/NVRAM version information */ +typedef struct { + + /* NVRAM or Registry */ + UINT_16 u2Part1CfgOwnVersion; + UINT_16 u2Part1CfgPeerVersion; + UINT_16 u2Part2CfgOwnVersion; + UINT_16 u2Part2CfgPeerVersion; + + /* Firmware */ + UINT_16 u2FwProductID; + UINT_16 u2FwOwnVersion; + UINT_16 u2FwPeerVersion; + +} WIFI_VER_INFO_T, *P_WIFI_VER_INFO_T; + + +#if CFG_ENABLE_WIFI_DIRECT +/* +* p2p function pointer structure +*/ + +typedef struct _P2P_FUNCTION_LINKER { + P2P_REMOVE prP2pRemove; +// NIC_P2P_MEDIA_STATE_CHANGE prNicP2pMediaStateChange; +// SCAN_UPDATE_P2P_DEVICE_DESC prScanUpdateP2pDeviceDesc; +// P2P_FSM_RUN_EVENT_RX_PROBE_RESPONSE_FRAME prP2pFsmRunEventRxProbeResponseFrame; + P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; +// P2P_CALCULATE_WSC_IE_LEN_FOR_PROBE_RSP prP2pCalculateWSC_IELenForProbeRsp; +// P2P_GENERATE_WSC_IE_FOR_PROBE_RSP prP2pGenerateWSC_IEForProbeRsp; +// SCAN_REMOVE_P2P_BSS_DESC prScanRemoveP2pBssDesc; +// P2P_HANDLE_SEC_CHECK_RSP prP2pHandleSecCheckRsp; + P2P_NET_REGISTER prP2pNetRegister; + P2P_NET_UNREGISTER prP2pNetUnregister; + P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; /* All IEs generated from supplicant. */ + P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; /* All IEs generated from supplicant. */ +} P2P_FUNCTION_LINKER, *P_P2P_FUNCTION_LINKER; + + +#endif + +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct _ADAPTER_T { + UINT_8 ucRevID; + + UINT_16 u2NicOpChnlNum; + + BOOLEAN fgIsEnableWMM; + BOOLEAN fgIsWmmAssoc; /* This flag is used to indicate that WMM is enable in current BSS */ + + UINT_32 u4OsPacketFilter; // packet filter used by OS + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_32 u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + + ENUM_BAND_T aePreferBand[NETWORK_TYPE_INDEX_NUM]; + + /* ADAPTER flags */ + UINT_32 u4Flags; + UINT_32 u4HwFlags; + + BOOLEAN fgIsRadioOff; + + BOOLEAN fgIsEnterD3ReqIssued; + + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + + ENUM_PHY_TYPE_INDEX_T eCurrentPhyType; /* Current selection basing on the set of Available PHY Types */ + +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + UINT_32 u4CoalescingBufCachedSize; + PUINT_8 pucCoalescingBufCached; +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* Buffer for CMD_INFO_T, Mgt packet and mailbox message */ + BUF_INFO_T rMgtBufInfo; + BUF_INFO_T rMsgBufInfo; + PUINT_8 pucMgtBufCached; + UINT_32 u4MgtBufCachedSize; + UINT_8 aucMsgBuf[MSG_BUFFER_SIZE]; +#if CFG_DBG_MGT_BUF + UINT_32 u4MemAllocDynamicCount; /* Debug only */ + UINT_32 u4MemFreeDynamicCount; /* Debug only */ +#endif + + STA_RECORD_T arStaRec[CFG_STA_REC_NUM]; + + /* Element for TX PATH */ + TX_CTRL_T rTxCtrl; + QUE_T rFreeCmdList; + CMD_INFO_T arHifCmdDesc[CFG_TX_MAX_CMD_PKT_NUM]; + + /* Element for RX PATH */ + RX_CTRL_T rRxCtrl; + + P_SDIO_CTRL_T prSDIOCtrl; + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + /* Element for MT6620 E1 HIFSYS workaround */ + BOOLEAN fgIsClockGatingEnabled; +#endif + + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8 ]; + + UINT_32 u4IntStatus; + + ENUM_ACPI_STATE_T rAcpiState; + + BOOLEAN fgIsIntEnable; + BOOLEAN fgIsIntEnableWithLPOwnSet; + + BOOLEAN fgIsFwOwn; + BOOLEAN fgWiFiInSleepyState; + + UINT_32 u4PwrCtrlBlockCnt; + + QUE_T rPendingCmdQueue; + + P_GLUE_INFO_T prGlueInfo; + + UINT_8 ucCmdSeqNum; + UINT_8 ucTxSeqNum; + +#if 1//CFG_SUPPORT_WAPI + BOOLEAN fgUseWapi; +#endif + + /* RF Test flags */ + BOOLEAN fgTestMode; + + /* WLAN Info for DRIVER_CORE OID query */ + WLAN_INFO_T rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PRegistered; + ENUM_NET_REG_STATE_T rP2PNetRegState; + BOOLEAN fgIsWlanLaunched; + P_P2P_INFO_T prP2pInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + OS_SYSTIME rP2pLinkQualityUpdateTime; + BOOLEAN fgIsP2pLinkQualityValid; + EVENT_LINK_QUALITY rP2pLinkQuality; +#endif +#endif + + /* Online Scan Option */ + BOOLEAN fgEnOnlineScan; + + /* Online Scan Option */ + BOOLEAN fgDisBcnLostDetection; + + /* MAC address */ + PARAM_MAC_ADDRESS rMyMacAddr; + + /* Wake-up Event for WOL */ + UINT_32 u4WakeupEventEnable; + + /* Event Buffering */ + EVENT_STATISTICS rStatStruct; + OS_SYSTIME rStatUpdateTime; + BOOLEAN fgIsStatValid; + + EVENT_LINK_QUALITY rLinkQuality; + OS_SYSTIME rLinkQualityUpdateTime; + BOOLEAN fgIsLinkQualityValid; + OS_SYSTIME rLinkRateUpdateTime; + BOOLEAN fgIsLinkRateValid; + + /* WIFI_VAR_T */ + WIFI_VAR_T rWifiVar; + + /* MTK WLAN NIC driver IEEE 802.11 MIB */ + IEEE_802_11_MIB_T rMib; + + /* Mailboxs for inter-module communication */ + MBOX_T arMbox[MBOX_ID_TOTAL_NUM]; + + /* Timers for OID Pending Handling */ + TIMER_T rOidTimeoutTimer; + + /* Root Timer for cnm_timer module */ + ROOT_TIMER rRootTimer; + + /* RLM maintenance */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_SYS_PROTECT_MODE_T eSysProtectMode; + ENUM_GF_MODE_T eSysHtGfMode; + ENUM_RIFS_MODE_T eSysTxRifsMode; + ENUM_SYS_PCO_PHASE_T eSysPcoPhase; + + P_DOMAIN_INFO_ENTRY prDomainInfo; + + /* QM */ + QUE_MGT_T rQM; + + CNM_INFO_T rCnmInfo; + + UINT_32 u4PowerMode; + + UINT_32 u4CtiaPowerMode; + BOOLEAN fgEnCtiaPowerMode; + + UINT_32 fgEnArpFilter; + + UINT_32 u4UapsdAcBmp; + + UINT_32 u4MaxSpLen; + + UINT_32 u4PsCurrentMeasureEn; + + /* Version Information */ + WIFI_VER_INFO_T rVerInfo; + + /* 5GHz support (from F/W) */ + BOOLEAN fgIsHw5GBandDisabled; + BOOLEAN fgEnable5GBand; + BOOLEAN fgIsEepromUsed; + BOOLEAN fgIsEfuseValid; + BOOLEAN fgIsEmbbededMacAddrValid; + + /* Packet Forwarding Tracking */ + INT_32 i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + UINT_8 ucRddStatus; +#endif + + BOOL fgDisStaAgingTimeoutDetection; + +};/* end of _ADAPTER_T */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Macros for BSS_INFO_T - Flag of Net Active */ +/*----------------------------------------------------------------------------*/ +#define IS_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive) +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_AIS_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_AIS_INDEX) +#define IS_P2P_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_P2P_INDEX) +#define IS_BOW_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_BOW_INDEX) + +#define SET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = TRUE;} + +#define UNSET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = FALSE;} + +#define BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + _prBssInfo->fgIsNetActive = FALSE; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR(_prBssInfo->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = FALSE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } + +#if CFG_ENABLE_BT_OVER_WIFI +#define BOW_BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_BOW; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = TRUE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_IDLE;} + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_ACTIVE;} + +#define SET_NET_PWR_STATE_PS(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_PS;} + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_IDLE) + +#define IS_SCN_PWR_STATE_ACTIVE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_ACTIVE) + +#define IS_SCN_PWR_STATE_IDLE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_IDLE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ADAPTER_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h new file mode 100755 index 000000000000..d0be930e2a61 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h @@ -0,0 +1,323 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 $ +*/ + + + +/* +** $Log: bow.h $ + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Submit missing BoW header files. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW structure. + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add Activity Report definition. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix wrong BoW event size. + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * basic implementation for EVENT_BT_OVER_WIFI + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * sync. with design document for interface change. + * + * 04 02 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * Wi-Fi driver no longer needs to implement 802.11 PAL, thus replaced by wrapping command/event definitions + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * correct typo. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * update for all command/event needed to be supported by 802.11 PAL. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * +*/ + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +#define MAX_BOW_NUMBER_OF_CHANNEL 18 //(MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 //Does not know the schedule of the interference +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { + UINT_8 ucCommandId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; + +typedef struct _BT_OVER_WIFI_COMMAND { + AMPC_COMMAND_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_COMMAND, *P_AMPC_COMMAND; + +typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { + UINT_8 ucEventId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; + +typedef struct _BT_OVER_WIFI_EVENT { + AMPC_EVENT_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_EVENT, *P_AMPC_EVENT; + +typedef struct _CHANNEL_DESC_T { + UINT_8 ucChannelBand; + UINT_8 ucChannelNum; +} CHANNEL_DESC, P_CHANNEL_DESC; + +// Command Structures +typedef struct _BOW_SETUP_CONNECTION { +//Fixed to 2.4G + UINT_8 ucChannelNum; + UINT_8 ucReserved1; + UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucReserved2; + +//Pending, for future BOW 5G supporting. +/* UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucChannelListNum; + CHANNEL_DESC arChannelList[1]; +*/ +} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; + +typedef struct _BOW_DESTROY_CONNECTION { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; + +typedef struct _BOW_SET_PTK { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; + UINT_8 aucTemporalKey[16]; +} BOW_SET_PTK, *P_BOW_SET_PTK; + +typedef struct _BOW_READ_RSSI { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_RSSI, *P_BOW_READ_RSSI; + +typedef struct _BOW_READ_LINK_QUALITY { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; + +typedef struct _BOW_SHORT_RANGE_MODE { + UINT_8 aucPeerAddress[6]; + INT_8 cTxPower; + UINT_8 ucReserved; +} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; + +// Event Structures +typedef struct _BOW_COMMAND_STATUS { + UINT_8 ucStatus; + UINT_8 ucReserved[3]; +} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; + +typedef struct _BOW_MAC_STATUS { + UINT_8 aucMacAddr[6]; + UINT_8 ucAvailability; + UINT_8 ucNumOfChannel; + CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; + +typedef struct _BOW_LINK_CONNECTED { + CHANNEL_DESC rChannel; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; + +typedef struct _BOW_LINK_DISCONNECTED { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; + +typedef struct _BOW_RSSI { + INT_8 cRssi; + UINT_8 aucReserved[3]; +} BOW_RSSI, *P_BOW_RSSI; + +typedef struct _BOW_LINK_QUALITY { + UINT_8 ucLinkQuality; + UINT_8 aucReserved[3]; +} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; + +typedef enum _ENUM_BOW_CMD_ID_T { + BOW_CMD_ID_GET_MAC_STATUS = 1, + BOW_CMD_ID_SETUP_CONNECTION, + BOW_CMD_ID_DESTROY_CONNECTION, + BOW_CMD_ID_SET_PTK, + BOW_CMD_ID_READ_RSSI, + BOW_CMD_ID_READ_LINK_QUALITY, + BOW_CMD_ID_SHORT_RANGE_MODE, + BOW_CMD_ID_GET_CHANNEL_LIST, +} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; + +typedef enum _ENUM_BOW_EVENT_ID_T { + BOW_EVENT_ID_COMMAND_STATUS = 1, + BOW_EVENT_ID_MAC_STATUS, + BOW_EVENT_ID_LINK_CONNECTED, + BOW_EVENT_ID_LINK_DISCONNECTED, + BOW_EVENT_ID_RSSI, + BOW_EVENT_ID_LINK_QUALITY, + BOW_EVENT_ID_CHANNEL_LIST, + BOW_EVENT_ID_CHANNEL_SELECTED, +} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; + +typedef enum _ENUM_BOW_DEVICE_STATE { + BOW_DEVICE_STATE_DISCONNECTED = 0, + BOW_DEVICE_STATE_DISCONNECTING, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL, + BOW_DEVICE_STATE_STARTING, + BOW_DEVICE_STATE_SCANNING, + BOW_DEVICE_STATE_CONNECTING, + BOW_DEVICE_STATE_CONNECTED, + BOW_DEVICE_STATE_NUM +} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h new file mode 100755 index 000000000000..2bb10b9b1390 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h @@ -0,0 +1,176 @@ +/* +** $Id: +*/ + +/*! \file "cmd_buf.h" + \brief In this file we define the structure for Command Packet. + + In this file we define the structure for Command Packet and the control unit + of MGMT Memory Pool. +*/ + + + +/* +** $Log: cmd_buf.h $ + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Enable change log +*/ + +#ifndef _CMD_BUF_H +#define _CMD_BUF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _COMMAND_TYPE { + COMMAND_TYPE_GENERAL_IOCTL, + COMMAND_TYPE_NETWORK_IOCTL, + COMMAND_TYPE_SECURITY_FRAME, + COMMAND_TYPE_MANAGEMENT_FRAME, + COMMAND_TYPE_NUM +} COMMAND_TYPE, *P_COMMAND_TYPE; + +typedef VOID (*PFN_CMD_DONE_HANDLER) ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +typedef VOID (*PFN_CMD_TIMEOUT_HANDLER) ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +struct _CMD_INFO_T { + QUE_ENTRY_T rQueEntry; + + COMMAND_TYPE eCmdType; + + UINT_16 u2InfoBufLen; /* This is actual CMD buffer length */ + PUINT_8 pucInfoBuffer; /* May pointer to structure in prAdapter */ + P_NATIVE_PACKET prPacket; /* only valid when it's a security frame */ + + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + UINT_8 ucStaRecIndex; /* only valid when it's a security frame */ + + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; + + BOOLEAN fgIsOid; /* Used to check if we need indicate */ + + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + BOOLEAN fgDriverDomainMCR; /* Access Driver Domain MCR, for CMD_ID_ACCESS_REG only */ + UINT_8 ucCmdSeqNum; + UINT_32 u4SetInfoLen; /* Indicate how many byte we read for Set OID */ + + /* information indicating by OID/ioctl */ + PVOID pvInformationBuffer; + UINT_32 u4InformationBufferLength; + + /* private data */ + UINT_32 u4PrivateData; +}; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +cmdBufInitialize ( + IN P_ADAPTER_T prAdapter + ); + +P_CMD_INFO_T +cmdBufAllocateCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Length + ); + +VOID +cmdBufFreeCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +/*----------------------------------------------------------------------------*/ +/* Routines for CMDs */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, + OUT PVOID pvSetQueryBuffer, + IN UINT_32 u4SetQueryBufferLen + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CMD_BUF_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h new file mode 100755 index 000000000000..e67727d7653d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h @@ -0,0 +1,609 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hal.h#1 $ +*/ + +/*! \file "hal.h" + \brief The declaration of hal functions + + N/A +*/ + + + +/* +** $Log: hal.h $ + * + * 04 01 2011 tsaiyuan.hsu + * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues + * fix the klocwork issues, 57500, 57501, 57502 and 57503. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 09 01 2010 cp.wu + * NULL + * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change zero-padding for TX port access to HAL. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * 4. correct some HAL implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-16 18:02:26 GMT mtk02752 +** include precomp.h +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:16 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 13:54:15 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-11 10:36:01 GMT mtk01084 +** modify HAL functions +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-09 22:56:28 GMT mtk01084 +** modify HW access routines +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:50:09 GMT mtk01084 +** add new macro HAL_TX_PORT_WR +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:08:10 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:50 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-05-18 14:28:10 GMT mtk01084 +** fix issue in HAL_DRIVER_OWN_BY_SDIO_CMD52() +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-11 17:26:33 GMT mtk01084 +** modify the bit definition to check driver own status +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:30:22 GMT mtk01461 +** Fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:50:34 GMT mtk01461 +** Redefine HAL_PORT_RD/WR macro for SW pre test +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-24 09:46:49 GMT mtk01084 +** fix LINT error +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 16:53:38 GMT mtk01084 +** add HAL_DRIVER_OWN_BY_SDIO_CMD52() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:53:13 GMT mtk01426 +** Fixed lint warn +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:20 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _HAL_H +#define _HAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* Macros for flag operations for the Adapter structure */ +#define HAL_SET_FLAG(_M, _F) ((_M)->u4HwFlags |= (_F)) +#define HAL_CLEAR_FLAG(_M, _F) ((_M)->u4HwFlags &= ~(_F)) +#define HAL_TEST_FLAG(_M, _F) ((_M)->u4HwFlags & (_F)) +#define HAL_TEST_FLAGS(_M, _F) (((_M)->u4HwFlags & (_F)) == (_F)) + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ + { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("HAL_MCR_RD access fail! 0x%x: 0x%x \n", _u4Offset, *_pu4Value)); \ + } \ + } else { \ + DBGLOG(HAL, WARN, ("ignore HAL_MCR_RD access! 0x%x\n", _u4Offset)); \ + } \ + } + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ + { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("HAL_MCR_WR access fail! 0x%x: 0x%x \n", _u4Offset, _u4Value)); \ + } \ + } else { \ + DBGLOG(HAL, WARN, ("ignore HAL_MCR_WR access! 0x%x: 0x%x \n", _u4Offset, _u4Value)); \ + } \ + } + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + { \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("HAL_PORT_RD access fail! 0x%x\n", _u4Port)); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, ("ignore HAL_PORT_RD access! 0x%x\n", _u4Port)); \ + } \ + } + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + { \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("HAL_PORT_WR access fail! 0x%x\n", _u4Port)); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, ("ignore HAL_PORT_WR access! 0x%x\n", _u4Port)); \ + } \ + } + +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("HAL_BYTE_WR access fail! 0x%x\n", _u4Port)); \ + } \ + else { \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, ("ignore HAL_BYTE_WR access! 0x%x\n", _u4Port)); \ + } \ + } + + +#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ + { \ + UINT_8 ucBuf = BIT(1); \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevReadAfterWriteWithSdioCmd52(_prAdapter->prGlueInfo, MCR_WHLPCR_BYTE1, &ucBuf, 1) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, ("kalDevReadAfterWriteWithSdioCmd52 access fail!\n")); \ + } \ + else { \ + *_pfgDriverIsOwnReady = (ucBuf & BIT(0)) ? TRUE : FALSE; \ + } \ + } else { \ + DBGLOG(HAL, WARN, ("ignore HAL_DRIVER_OWN_BY_SDIO_CMD52 access!\n")); \ + } \ + } + +#else /* #if defined(_HIF_SDIO) */ +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value); \ + } + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value); \ + } + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize); \ + } + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize); \ + } + +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ + { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf); \ + } + +#endif /* #if defined(_HIF_SDIO) */ + + +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ + { \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + ((u4PortId == 0) ? MCR_WRDR0 : MCR_WRDR1), \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/) \ + } + +#define HAL_WRITE_TX_PORT(_prAdapter, _ucTxPortIdx, _u4Len, _pucBuf, _u4ValidBufSize) \ + { \ + ASSERT(_ucTxPortIdx < 2); \ + if((_u4ValidBufSize - _u4Len) >= sizeof(UINT_32)) { \ + /* fill with single dword of zero as TX-aggregation termination */ \ + *(PUINT_32) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + (_ucTxPortIdx == 0) ? MCR_WTDR0 : MCR_WTDR1, \ + _u4Len, \ + _pucBuf, \ + _u4ValidBufSize/*temp!!*//*4KByte*/) \ + } + +/* The macro to read the given MCR several times to check if the wait + condition come true. */ +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, _waitCondition, _waitDelay, _waitCount, _status) \ + { \ + UINT_32 count; \ + (_status) = FALSE; \ + for (count = 0; count < (_waitCount); count++) { \ + HAL_MCR_RD((_pAdapter), (_offset), (_pReadValue)); \ + if ((_waitCondition)) { \ + (_status) = TRUE; \ + break; \ + } \ + kalUdelay((_waitDelay)); \ + } \ + } + + +/* The macro to write 1 to a R/S bit and read it several times to check if the + command is done */ +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, _busyMask, _waitDelay, _waitCount, _status) \ + { \ + UINT_32 u4Temp; \ + UINT_32 u4Count = _waitCount; \ + (_status) = FALSE; \ + HAL_MCR_WR((_pAdapter), (_offset), (_writeValue)); \ + do { \ + kalUdelay((_waitDelay)); \ + HAL_MCR_RD((_pAdapter), (_offset), &u4Temp); \ + if (!(u4Temp & (_busyMask))) { \ + (_status) = TRUE; \ + break; \ + } \ + u4Count--; \ + } while (u4Count); \ + } + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (UINT_16)(u4Value & WCIR_CHIP_ID); \ + *pu2Version = (UINT_16)(u4Value & WCIR_REVISION_ID) >> 16; \ + } + +#define HAL_WAIT_WIFI_FUNC_READY(_prAdapter) \ + { \ + UINT_32 u4Value; \ + UINT_32 i; \ + for (i = 0; i < 100; i++) { \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + break; \ + } \ + NdisMSleep(10); \ + } \ + } + +#define HAL_INTR_DISABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_CLR) + +#define HAL_INTR_ENABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_SET) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + (WHLPCR_INT_EN_SET | WHLPCR_FW_OWN_REQ_SET)) + +#define HAL_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET) + +#define HAL_LP_OWN_CLR_OK(_prAdapter, _pfgResult) \ + { \ + UINT_32 i; \ + UINT_32 u4RegValue; \ + UINT_32 u4LoopCnt = 2048 / 8; \ + *_pfgResult = TRUE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR) \ + for (i = 0; i < u4LoopCnt; i++) { \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + break; \ + } \ + else { \ + kalUdelay(8); \ + } \ + } \ + if (i == u4LoopCnt) { \ + *_pfgResult = FALSE; \ + /*ERRORLOG(("LP cannot be own back (%ld)", u4LoopCnt));*/ \ + /* check the time of LP instructions need to perform from Sleep to On */ \ + /*ASSERT(0); */ \ + } \ + } + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ + { \ + HAL_MCR_RD(_prAdapter, \ + MCR_WASR, \ + pu4AbnormalReason); \ + } + + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_RX_ENHANCE_MODE_EN); \ + } + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_RX_ENHANCE_MODE_EN); \ + } + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) \ + { \ + UINT_32 u4Value, ucNum; \ + ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ + u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ + u4Value |= ((((UINT_32)ucNum) << 4) & WHCR_MAX_HIF_RX_LEN_NUM); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value); \ + } + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = TRUE;\ + } + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = FALSE;\ + } + +/* Note: enhance mode structure may also carried inside the buffer, + if the length of the buffer is long enough */ +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) \ + HAL_PORT_RD(prAdapter, \ + MCR_WHISR, \ + length, \ + pvBuf, \ + length) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, aucTxReleaseCount) \ + { \ + PUINT_32 pu4Value = (PUINT_32)aucTxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR1, \ + &pu4Value[1]); \ + } + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ + { \ + UINT_32 u4Value; \ + u4Value = 0; \ + HAL_MCR_RD(prAdapter, \ + MCR_WRPLR, \ + &u4Value); \ + *pu2Rx0Len = (UINT_16)u4Value; \ + *pu2Rx1Len = (UINT_16)(u4Value >> 16); \ + } + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) \ + { \ + PUINT_32 pu4Buf = (PUINT_32)pvBuf; \ + *pu4Status = pu4Buf[0]; \ + } + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) \ + { \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT(u4LenBufOut >= 8); \ + pu4BufOut[0] = pu4Buf[1]; \ + pu4BufOut[1] = pu4Buf[2]; \ + } + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) \ + { \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT((sizeof(au2Rx0Len) / sizeof(UINT_16)) >= 16); \ + ASSERT((sizeof(au2Rx1Len) / sizeof(UINT_16)) >= 16); \ + *pu2Rx0Num = (UINT_16)pu4Buf[3]; \ + *pu2Rx1Num = (UINT_16)(pu4Buf[3] >> 16); \ + kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ + kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ + } + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) \ + { \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + *pu4Mailbox0 = (UINT_16)pu4Buf[21]; \ + *pu4Mailbox1 = (UINT_16)pu4Buf[22]; \ + } + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_TX_DONE_INT) ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)) ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_ABNORMAL_INT) ? TRUE : FALSE) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_FW_OWN_BACK_INT) ? TRUE : FALSE) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) \ + { \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_WR(prAdapter, \ + ((u4MboxId == 0) ? MCR_H2DSM0R : MCR_H2DSM1R), \ + u4Data); \ + } + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) \ + { \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_RD(prAdapter, \ + ((u4MboxId == 0) ? MCR_D2HRM0R : MCR_D2HRM1R), \ + pu4Data); \ + } + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ + { \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ + HAL_MCR_WR(prAdapter, MCR_WHCR, \ + (fgEnableReadClear) ? \ + (u4Value | WHCR_W_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_W_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ + } + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HAL_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h new file mode 100755 index 000000000000..3895a7c3fc01 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h @@ -0,0 +1,227 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_rx.h#1 $ +*/ + +/*! \file "hif_rx.h" + \brief Provide HIF RX Header Information between F/W and Driver + + N/A +*/ + + +/* +** $Log: hif_rx.h $ + * + * 09 01 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * follow-ups for HIF_RX_HEADER_T update: + * 1) add TCL + * 2) add RCPI + * 3) add ChannelNumber + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:44:00 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-09 13:59:20 GMT MTK02468 +** Added HIF_RX_HDR parsing macros +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 19:54:54 GMT mtk02752 +** adopt HIF_RX_HEADER_T in new data path +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-29 19:51:19 GMT mtk01084 +** modify FW/ driver interface +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:33:58 GMT mtk01461 +** Add define of HW_APPENED_LEN +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:51:02 GMT mtk01461 +** Rename ENUM_HIF_RX_PKT_TYPE_T +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 12:05:03 GMT mtk01426 +** Remove __KAL_ATTRIB_PACKED__ and add hifDataTypeCheck() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:18:52 GMT mtk01426 +** Add comment to HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:23 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _HIF_RX_H +#define _HIF_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! HIF_RX_HEADER_T */ +// DW 0, Byte 1 +#define HIF_RX_HDR_PACKET_TYPE_MASK BITS(0,1) + +// DW 1, Byte 0 +#define HIF_RX_HDR_HEADER_LEN BITS(2,7) +#define HIF_RX_HDR_HEADER_LEN_OFFSET 2 +#define HIF_RX_HDR_HEADER_OFFSET_MASK BITS(0,1) + +// DW 1, Byte 1 +#define HIF_RX_HDR_80211_HEADER_FORMAT BIT(0) +#define HIF_RX_HDR_DO_REORDER BIT(1) +#define HIF_RX_HDR_PAL BIT(2) +#define HIF_RX_HDR_TCL BIT(3) +#define HIF_RX_HDR_NETWORK_IDX_MASK BITS(4,7) +#define HIF_RX_HDR_NETWORK_IDX_OFFSET 4 + +// DW 1, Byte 2, 3 +#define HIF_RX_HDR_SEQ_NO_MASK BITS(0,11) +#define HIF_RX_HDR_TID_MASK BITS(12,14) +#define HIF_RX_HDR_TID_OFFSET 12 +#define HIF_RX_HDR_BAR_FRAME BIT(15) + + + +#define HIF_RX_HDR_FLAG_AMP_WDS BIT(0) +#define HIF_RX_HDR_FLAG_802_11_FORMAT BIT(1) +#define HIF_RX_HDR_FLAG_BAR_FRAME BIT(2) +#define HIF_RX_HDR_FLAG_DO_REORDERING BIT(3) +#define HIF_RX_HDR_FLAG_CTRL_WARPPER_FRAME BIT(4) + +#define HIF_RX_HW_APPENDED_LEN 4 + +// For DW 2, Byte 3 - ucHwChannelNum +#define HW_CHNL_NUM_MAX_2G4 14 +#define HW_CHNL_NUM_MAX_4G_5G (255 - HW_CHNL_NUM_MAX_2G4) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _HIF_RX_HEADER_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucHerderLenOffset; + UINT_8 uc80211_Reorder_PAL_TCL; + UINT_16 u2SeqNoTid; + UINT_8 ucStaRecIdx; + UINT_8 ucRcpi; + UINT_8 ucHwChannelNum; + UINT_8 ucReserved; +} HIF_RX_HEADER_T, *P_HIF_RX_HEADER_T; + +typedef enum _ENUM_HIF_RX_PKT_TYPE_T { + HIF_RX_PKT_TYPE_DATA = 0, + HIF_RX_PKT_TYPE_EVENT, + HIF_RX_PKT_TYPE_TX_LOOPBACK, + HIF_RX_PKT_TYPE_MANAGEMENT, + HIF_RX_PKT_TYPE_NUM +} ENUM_HIF_RX_PKT_TYPE_T, *P_ENUM_HIF_RX_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define HIF_RX_HDR_SIZE sizeof(HIF_RX_HEADER_T) + +#define HIF_RX_HDR_GET_80211_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_80211_HEADER_FORMAT) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_REORDER_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_DO_REORDER) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_PAL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_PAL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_TCL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_TCL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_NETWORK_IDX(_prHifRxHdr) \ + ((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_NETWORK_IDX_MASK)\ + >> HIF_RX_HDR_NETWORK_IDX_OFFSET) + + +#define HIF_RX_HDR_GET_TID(_prHifRxHdr) \ + ((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_TID_MASK)\ + >> HIF_RX_HDR_TID_OFFSET) +#define HIF_RX_HDR_GET_SN(_prHifRxHdr) \ + (((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_SEQ_NO_MASK) +#define HIF_RX_HDR_GET_BAR_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_BAR_FRAME)? TRUE: FALSE)) + + +#define HIF_RX_HDR_GET_CHNL_NUM(_prHifRxHdr) \ + ( ( ((_prHifRxHdr)->ucHwChannelNum) > HW_CHNL_NUM_MAX_4G_5G ) ? \ + ( ((_prHifRxHdr)->ucHwChannelNum) - HW_CHNL_NUM_MAX_4G_5G ) : \ + ((_prHifRxHdr)->ucHwChannelNum) ) + +/* To do: support more bands other than 2.4G and 5G */ +#define HIF_RX_HDR_GET_RF_BAND(_prHifRxHdr) \ + ( ( ((_prHifRxHdr)->ucHwChannelNum) <= HW_CHNL_NUM_MAX_2G4 ) ? \ + BAND_2G4 : BAND_5G) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +__KAL_INLINE__ VOID +hifDataTypeCheck ( + VOID + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +__KAL_INLINE__ VOID +hifDataTypeCheck ( + VOID + ) +{ + DATA_STRUC_INSPECTING_ASSERT(sizeof(HIF_RX_HEADER_T) == 12); + + return; +} + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h new file mode 100755 index 000000000000..3a04ce55d9be --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h @@ -0,0 +1,225 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 $ +*/ + + + +/* +** $Log: hif_tx.h $ + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill extra information for revised HIF_TX_HEADER. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate + * 2) add packet type for indicating management frames + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * 2. follow MSDN defined behavior when associates to another AP + * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 01 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:40 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-24 19:55:11 GMT mtk02752 +** adopt HIF_TX_HEADER_T in new data path +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-23 17:54:13 GMT mtk02752 +** CMD_HDR_SIZE = (sizeof(WIFI_CMD_T)) to follow up CM's CMD/EVENT documentation +** +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-17 22:41:10 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-17 17:34:07 GMT mtk02752 +** remove HIF_TX_BUFF_COUNT_TC0 (move to nic_tx.h) +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-17 12:14:12 GMT mtk02752 +** add initial value for HIF_TX_BUFF_COUNT_TC5 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-13 13:54:18 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-04 14:11:14 GMT mtk01084 +** modify SW TX data format +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-29 19:51:53 GMT mtk01084 +** modify FW/ driver interface +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-20 12:22:46 GMT mtk01461 +** Add SeqNum field to CMD Header +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:40:52 GMT mtk01461 +** Update the Log Sign +*/ + +#ifndef _HIF_TX_H +#define _HIF_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Maximum buffer size for individual HIF TCQ Buffer */ +#define HIF_TX_BUFF_MAX_SIZE 1552 /* Reserved field was not included */ + +/* Maximum buffer count for individual HIF TCQ */ +#define HIF_TX_BUFF_COUNT_TC0 3 +#define HIF_TX_BUFF_COUNT_TC1 3 +#define HIF_TX_BUFF_COUNT_TC2 3 +#define HIF_TX_BUFF_COUNT_TC3 3 +#define HIF_TX_BUFF_COUNT_TC4 2 + +#define TX_HDR_SIZE sizeof(HIF_TX_HEADER_T) + +#define CMD_HDR_SIZE sizeof(WIFI_CMD_T) + +#define CMD_PKT_SIZE_FOR_IMAGE 2048 /* !< 2048 Bytes CMD payload buffer */ + + +/*! NIC_HIF_TX_HEADER_T */ +// DW 0, Byte 0,1 +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0,11) +#define HIF_TX_HDR_USER_PRIORITY_OFFSET 12 + +// DW 0, Byte 2 +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0,7) + +// DW 0, Byte 3 +#define HIF_TX_HDR_IP_CSUM BIT(0) +#define HIF_TX_HDR_TCP_CSUM BIT(1) +#define HIF_TX_HDR_RESOURCE_MASK BITS(2,5) +#define HIF_TX_HDR_RESOURCE_OFFSET 2 +#define HIF_TX_HDR_PACKET_TYPE_MASK BITS(6,7) +#define HIF_TX_HDR_PACKET_TYPE_OFFSET 6 + +// DW 1, Byte 0 +#define HIF_TX_HDR_WLAN_HEADER_LEN_MASK BITS(0,5) + +// DW 1, Byte 1 +#define HIF_TX_HDR_FORMAT_ID_MASK BITS(0,2) +#define HIF_TX_HDR_NETWORK_TYPE_MASK BITS(4,5) +#define HIF_TX_HDR_NETWORK_TYPE_OFFSET 4 +#define HIF_TX_HDR_FLAG_1X_FRAME_MASK BIT(6) +#define HIF_TX_HDR_FLAG_1X_FRAME_OFFSET 6 +#define HIF_TX_HDR_FLAG_802_11_FORMAT_MASK BIT(7) +#define HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET 7 + + +// DW2, Byte 3 +#define HIF_TX_HDR_PS_FORWARDING_TYPE_MASK BITS(0,1) +#define HIF_TX_HDR_PS_SESSION_ID_MASK BITS(2,4) +#define HIF_TX_HDR_PS_SESSION_ID_OFFSET 2 +#define HIF_TX_HDR_BURST_END_MASK BIT(5) +#define HIF_TX_HDR_BURST_END_OFFSET 5 + +// DW3, Byte 1 +#define HIF_TX_HDR_NEED_ACK BIT(0) +#define HIF_TX_HDR_BIP BIT(1) +#define HIF_TX_HDR_BASIC_RATE BIT(2) + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _HIF_HW_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + UINT_8 aucBuffer[0]; +} HIF_HW_TX_HEADER_T, *P_HIF_HW_TX_HEADER_T; + +typedef struct _HIF_TX_HEADER_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucWlanHeaderLength; + UINT_8 ucPktFormtId_Flags; + UINT_16 u2LLH; /* for BOW */ + UINT_16 u2SeqNo; /* for BOW */ + UINT_8 ucStaRecIdx; + UINT_8 ucForwardingType_SessionID_Reserved; + UINT_8 ucPacketSeqNo; + UINT_8 ucAck_BIP_BasicRate; + UINT_8 aucReserved[2]; +} HIF_TX_HEADER_T, *P_HIF_TX_HEADER_T; + +typedef enum _ENUM_HIF_TX_PKT_TYPE_T { + HIF_TX_PKT_TYPE_DATA = 0, + HIF_TX_PKT_TYPE_CMD, + HIF_TX_PKT_TYPE_HIF_LOOPBACK, + HIF_TX_PKT_TYPE_MANAGEMENT, + HIF_TX_PKT_TYPE_NUM +} ENUM_HIF_TX_PKT_TYPE_T, *P_ENUM_HIF_TX_PKT_TYPE_T; + +typedef enum _ENUM_HIF_OOB_CTRL_PKT_TYPE_T { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +} ENUM_HIF_OOB_CTRL_PKT_TYPE_T, *P_ENUM_HIF_OOB_CTRL_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +__KAL_INLINE__ VOID +hif_txDataTypeCheck ( + VOID + ); + +__KAL_INLINE__ VOID +hif_txDataTypeCheck ( + VOID + ) +{ + DATA_STRUC_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); + + return; +} + +#endif /*_HIF_TX_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h new file mode 100755 index 000000000000..f22154bc9e3b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h @@ -0,0 +1,2185 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mac.h#1 $ +*/ + +/*! \file "mac.h" + \brief Brief description. + + Detail description. +*/ + + + +/* +** $Log: mac.h $ + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h and let the sw structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 05 06 2011 wh.su + * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send the wrong beacon make driver got incorrect support rate set + * Add the length check before access the ie length filed. + * + * 05 06 2011 wh.su + * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send the wrong beacon make driver got incorrect support rate set + * adding the length check before processing next ie.. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discover ability support. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Some action frame define is not belong to P2P. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Add some service discovery MAC define, phase I. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 13 2010 cp.wu + * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork + * suppress warning reported by Klockwork. + * + * 11 01 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * revert to previous revision. (this file is not necessary to be changed) + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 02 2010 yuche.tsai + * NULL + * 1. Add P2P MAC define. + * 2. Add scan device found event + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add WFA specific OUI. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P IE ID & Vendor OUI TYPE for P2P. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge MAC.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added OFFSET_BAR_SSC_SN +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:00:24 GMT MTK02468 +** Added offsets and masks for the BA Parameter Set filed +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:26 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _MAC_H +#define _MAC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//3 /* --------------- Constants for Ethernet/802.11 MAC --------------- */ +/* MAC Address */ +#define MAC_ADDR_LEN 6 + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_IPX 0x8137 // Novell IPX +#define ETH_P_AARP 0x80F3 // AppleTalk Address Resolution Protocol (AARP) +#define ETH_P_IPV6 0x86DD + +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define LLC_LEN 8 // LLC(3) + SNAP(3) + EtherType(2) + +#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +/* Ethernet Frame Field Size, in byte */ +#define ETHER_HEADER_LEN 14 +#define ETHER_TYPE_LEN 2 +#define ETHER_MIN_PKT_SZ 60 +#define ETHER_MAX_PKT_SZ 1514 + +/* IEEE 802.11 WLAN Frame Field Size, in byte */ +#define WLAN_MAC_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_HEADER_A4_LEN 30 /* Address 4 included */ +#define WLAN_MAC_HEADER_QOS_LEN 26 /* QoS Control included */ +#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 /* QoS Control and HTC included */ +#define WLAN_MAC_HEADER_A4_QOS_LEN 32 /* Address 4 and QoS Control included */ +#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 /* Address 4, QoS Control and HTC included */ +#define WLAN_MAC_MGMT_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 /* HTC included */ + +#define QOS_CTRL_LEN 2 +#define HT_CTRL_LEN 4 + +#define WLAN_MAC_CTS_ACK_LEN WLAN_MAC_CTS_ACK_FRAME_HEADER_LEN + FCS_LEN + +/* 6.2.1.1.2 Semantics of the service primitive */ +#define MSDU_MAX_LENGTH 2304 + +/* 7.1.3.3.3 Broadcast BSSID */ +#define BC_BSSID BC_MAC_ADDR + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.3.1.6 Listen Interval field */ +#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 // In unit of AP's DTIM interval, +#define DEFAULT_LISTEN_INTERVAL 10 + +/* 7.3.2.1 Broadcast(Wildcard) SSID */ +#define BC_SSID "" +#define BC_SSID_LEN 0 + +/* 7.3.2.2 Data Rate Value */ +#define RATE_1M 2 /* 1M in unit of 500kb/s */ +#define RATE_2M 4 /* 2M */ +#define RATE_5_5M 11 /* 5.5M */ +#define RATE_11M 22 /* 11M */ +#define RATE_22M 44 /* 22M */ +#define RATE_33M 66 /* 33M */ +#define RATE_6M 12 /* 6M */ +#define RATE_9M 18 /* 9M */ +#define RATE_12M 24 /* 12M */ +#define RATE_18M 36 /* 18M */ +#define RATE_24M 48 /* 24M */ +#define RATE_36M 72 /* 36M */ +#define RATE_48M 96 /* 48M */ +#define RATE_54M 108 /* 54M */ +/* 7.3.2.14 BSS membership selector */ +#define RATE_HT_PHY 127 /* BSS Selector - Clause 20. HT PHY */ +#define RATE_MASK BITS(0,6) /* mask bits for the rate */ +#define RATE_BASIC_BIT BIT(7) /* mask bit for the rate belonging to the BSSBasicRateSet */ + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 9.2.10 DIFS */ +#define DIFS 2 /* 2 x aSlotTime */ + +/* 11.3 STA Authentication and Association */ +#define STA_STATE_1 0 /* Accept Class 1 frames */ +#define STA_STATE_2 1 /* Accept Class 1 & 2 frames */ +#define STA_STATE_3 2 /* Accept Class 1,2 & 3 frames */ + +/* 15.4.8.5 802.11k RCPI-dBm mapping*/ +#define NDBM_LOW_BOUND_FOR_RCPI 110 +#define RCPI_LOW_BOUND 0 +#define RCPI_HIGH_BOUND 220 +#define RCPI_MEASUREMENT_NOT_AVAILABLE 255 + + +/* PHY characteristics */ +/* 17.4.4/18.3.3/19.8.4 Slot Time (aSlotTime) */ +#define SLOT_TIME_LONG 20 /* Long Slot Time */ +#define SLOT_TIME_SHORT 9 /* Short Slot Time */ + +#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG /* 802.11b aSlotTime */ +#define SLOT_TIME_OFDM SLOT_TIME_SHORT /* 802.11a aSlotTime(20M Spacing) */ +#define SLOT_TIME_OFDM_10M_SPACING 13 /* 802.11a aSlotTime(10M Spacing) */ +#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG /* 802.11g aSlotTime(Long) */ +#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT /* 802.11g aSlotTime(Short) */ + +/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ +#define CWMIN_OFDM 15 /* 802.11a aCWmin */ +#define CWMAX_OFDM 1023 /* 802.11a aCWmax */ + +#define CWMIN_HR_DSSS 31 /* 802.11b aCWmin */ +#define CWMAX_HR_DSSS 1023 /* 802.11b aCWmax */ + +#define CWMIN_ERP_0 31 /* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ +#define CWMIN_ERP_1 15 /* 802.11g aCWmin(1) */ +#define CWMAX_ERP 1023 /* 802.11g aCWmax */ + +/* Short Inter-Frame Space (aSIFSTime) */ +/* 15.3.3 802.11b aSIFSTime */ +#define SIFS_TIME_HR_DSSS 10 +/* 17.4.4 802.11a aSIFSTime */ +#define SIFS_TIME_OFDM 16 +/* 19.8.4 802.11g aSIFSTime */ +#define SIFS_TIME_ERP 10 + +/* 15.4.6.2 Number of operating channels */ +#define CH_1 0x1 +#define CH_2 0x2 +#define CH_3 0x3 +#define CH_4 0x4 +#define CH_5 0x5 +#define CH_6 0x6 +#define CH_7 0x7 +#define CH_8 0x8 +#define CH_9 0x9 +#define CH_10 0xa +#define CH_11 0xb +#define CH_12 0xc +#define CH_13 0xd +#define CH_14 0xe + +#define MAXIMUM_OPERATION_CHANNEL_LIST 32 + + +//3 /* --------------- IEEE 802.11 PICS --------------- */ +/* Annex D - dot11OperationEntry 2 */ +#define DOT11_RTS_THRESHOLD_MIN 0 +#define DOT11_RTS_THRESHOLD_MAX 2347 // from Windows DDK +//#define DOT11_RTS_THRESHOLD_MAX 3000 // from Annex D + +#define DOT11_RTS_THRESHOLD_DEFAULT \ + DOT11_RTS_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 5 */ +#define DOT11_FRAGMENTATION_THRESHOLD_MIN 256 +#define DOT11_FRAGMENTATION_THRESHOLD_MAX 2346 // from Windows DDK +//#define DOT11_FRAGMENTATION_THRESHOLD_MAX 3000 // from Annex D + +#define DOT11_FRAGMENTATION_THRESHOLD_DEFAULT \ + DOT11_FRAGMENTATION_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 6 */ +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MIN 1 +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 4095 // 802.11 define 512 + // MT5921 only aceept N <= 4095 + +/* Annex D - dot11OperationEntry 7 */ +#define DOT11_RECEIVE_LIFETIME_TU_MIN 1 +#define DOT11_RECEIVE_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_RECEIVE_LIFETIME_TU_DEFAULT 4096 // 802.11 define 512 + +/* Annex D - dot11StationConfigEntry 12 */ +#define DOT11_BEACON_PERIOD_MIN 1 // TU. +#define DOT11_BEACON_PERIOD_MAX 0xffff // TU. +#define DOT11_BEACON_PERIOD_DEFAULT 100 // TU. + +/* Annex D - dot11StationConfigEntry 13 */ +#define DOT11_DTIM_PERIOD_MIN 1 // TU. +#define DOT11_DTIM_PERIOD_MAX 255 // TU. +#define DOT11_DTIM_PERIOD_DEFAULT 1 // TU. + +/* Annex D - dot11RegDomainsSupportValue */ +#define REGULATION_DOMAIN_FCC 0x10 /* FCC (US) */ +#define REGULATION_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define REGULATION_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define REGULATION_DOMAIN_SPAIN 0x31 /* Spain */ +#define REGULATION_DOMAIN_FRANCE 0x32 /* France */ +#define REGULATION_DOMAIN_JAPAN 0x40 /* MKK (Japan) */ +#define REGULATION_DOMAIN_CHINA 0x50 /* China */ +#define REGULATION_DOMAIN_OTHER 0x00 /* Other */ + + + +//3 /* --------------- IEEE 802.11 MAC header fields --------------- */ +/* 7.1.3.1 Masks for the subfields in the Frame Control field */ +#define MASK_FC_PROTOCOL_VER BITS(0,1) +#define MASK_FC_TYPE BITS(2,3) +#define MASK_FC_SUBTYPE BITS(4,7) +#define MASK_FC_SUBTYPE_QOS_DATA BIT(7) +#define MASK_FC_TO_DS BIT(8) +#define MASK_FC_FROM_DS BIT(9) +#define MASK_FC_MORE_FRAG BIT(10) +#define MASK_FC_RETRY BIT(11) +#define MASK_FC_PWR_MGT BIT(12) +#define MASK_FC_MORE_DATA BIT(13) +#define MASK_FC_PROTECTED_FRAME BIT(14) +#define MASK_FC_ORDER BIT(15) + +#define MASK_FRAME_TYPE (MASK_FC_TYPE | MASK_FC_SUBTYPE) +#define MASK_TO_DS_FROM_DS (MASK_FC_TO_DS | MASK_FC_FROM_DS) + +#define MAX_NUM_OF_FC_SUBTYPES 16 +#define OFFSET_OF_FC_SUBTYPE 4 + + +/* 7.1.3.1.2 MAC frame types and subtypes */ +#define MAC_FRAME_TYPE_MGT 0 +#define MAC_FRAME_TYPE_CTRL BIT(2) +#define MAC_FRAME_TYPE_DATA BIT(3) +#define MAC_FRAME_TYPE_QOS_DATA (MAC_FRAME_TYPE_DATA | MASK_FC_SUBTYPE_QOS_DATA) + +#define MAC_FRAME_ASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0000) +#define MAC_FRAME_ASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0010) +#define MAC_FRAME_REASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0020) +#define MAC_FRAME_REASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0030) +#define MAC_FRAME_PROBE_REQ (MAC_FRAME_TYPE_MGT | 0x0040) +#define MAC_FRAME_PROBE_RSP (MAC_FRAME_TYPE_MGT | 0x0050) +#define MAC_FRAME_BEACON (MAC_FRAME_TYPE_MGT | 0x0080) +#define MAC_FRAME_ATIM (MAC_FRAME_TYPE_MGT | 0x0090) +#define MAC_FRAME_DISASSOC (MAC_FRAME_TYPE_MGT | 0x00A0) +#define MAC_FRAME_AUTH (MAC_FRAME_TYPE_MGT | 0x00B0) +#define MAC_FRAME_DEAUTH (MAC_FRAME_TYPE_MGT | 0x00C0) +#define MAC_FRAME_ACTION (MAC_FRAME_TYPE_MGT | 0x00D0) +#define MAC_FRAME_ACTION_NO_ACK (MAC_FRAME_TYPE_MGT | 0x00E0) + + +#define MAC_FRAME_CONTRL_WRAPPER (MAC_FRAME_TYPE_CTRL | 0x0070) +#define MAC_FRAME_BLOCK_ACK_REQ (MAC_FRAME_TYPE_CTRL | 0x0080) +#define MAC_FRAME_BLOCK_ACK (MAC_FRAME_TYPE_CTRL | 0x0090) +#define MAC_FRAME_PS_POLL (MAC_FRAME_TYPE_CTRL | 0x00A0) +#define MAC_FRAME_RTS (MAC_FRAME_TYPE_CTRL | 0x00B0) +#define MAC_FRAME_CTS (MAC_FRAME_TYPE_CTRL | 0x00C0) +#define MAC_FRAME_ACK (MAC_FRAME_TYPE_CTRL | 0x00D0) +#define MAC_FRAME_CF_END (MAC_FRAME_TYPE_CTRL | 0x00E0) +#define MAC_FRAME_CF_END_CF_ACK (MAC_FRAME_TYPE_CTRL | 0x00F0) + +#define MAC_FRAME_DATA (MAC_FRAME_TYPE_DATA | 0x0000) +#define MAC_FRAME_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0010) +#define MAC_FRAME_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0020) +#define MAC_FRAME_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0030) +#define MAC_FRAME_NULL (MAC_FRAME_TYPE_DATA | 0x0040) +#define MAC_FRAME_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0050) +#define MAC_FRAME_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0060) +#define MAC_FRAME_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0070) +#define MAC_FRAME_QOS_DATA (MAC_FRAME_TYPE_DATA | 0x0080) +#define MAC_FRAME_QOS_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0090) +#define MAC_FRAME_QOS_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00A0) +#define MAC_FRAME_QOS_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00B0) +#define MAC_FRAME_QOS_NULL (MAC_FRAME_TYPE_DATA | 0x00C0) +#define MAC_FRAME_QOS_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00E0) +#define MAC_FRAME_QOS_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00F0) + +/* 7.1.3.2 Mask for the AID value in the Duration/ID field */ +#define MASK_DI_DURATION BITS(0,14) +#define MASK_DI_AID BITS(0,13) +#define MASK_DI_AID_MSB BITS(14,15) +#define MASK_DI_CFP_FIXED_VALUE BIT(15) + +/* 7.1.3.4 Masks for the subfields in the Sequence Control field */ +#define MASK_SC_SEQ_NUM BITS(4,15) +#define MASK_SC_SEQ_NUM_OFFSET 4 +#define MASK_SC_FRAG_NUM BITS(0,3) +#define INVALID_SEQ_CTRL_NUM 0x000F /* According to 6.2.1.1.2 + * FRAG_NUM won't equal to 15 + */ + +/* 7.1.3.5 QoS Control field */ +#define TID_NUM 16 +#define TID_MASK BITS(0,3) +#define EOSP BIT(4) +#define ACK_POLICY BITS(5,6) +#define A_MSDU_PRESENT BIT(7) + +#define MASK_QC_TID BITS(0,3) +#define MASK_QC_EOSP BIT(4) +#define MASK_QC_EOSP_OFFSET 4 +#define MASK_QC_ACK_POLICY BITS(5, 6) +#define MASK_QC_ACK_POLICY_OFFSET 5 +#define MASK_QC_A_MSDU_PRESENT BIT(7) + +/* 7.1.3.5a HT Control field */ +#define HT_CTRL_LINK_ADAPTATION_CTRL BITS(0,15) +#define HT_CTRL_CALIBRATION_POSITION BITS(16,17) +#define HT_CTRL_CALIBRATION_SEQUENCE BITS(18,19) +#define HT_CTRL_CSI_STEERING BITS(22,23) +#define HT_CTRL_NDP_ANNOUNCEMENT BIT(24) +#define HT_CTRL_AC_CONSTRAINT BIT(30) +#define HT_CTRL_RDG_MORE_PPDU BIT(31) + +#define LINK_ADAPTATION_CTRL_TRQ BIT(1) +#define LINK_ADAPTATION_CTRL_MAI_MRQ BIT(2) +#define LINK_ADAPTATION_CTRL_MAI_MSI BITS(3,5) +#define LINK_ADAPTATION_CTRL_MFSI BITS(6,8) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_CMD BITS(9,11) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_DATA BITS(12,15) + +/* 7.1.3.5.3 Ack Policy subfield*/ +#define ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ 0 +#define ACK_POLICY_NO_ACK 1 +#define ACK_POLICY_NO_EXPLICIT_ACK_PSMP_ACK 2 +#define ACK_POLICY_BA 3 + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +#define PSPOLL_FRAME_LEN 16 /* w/o FCS */ + +/* 7.2.7.1 BAR */ +#define OFFSET_BAR_SSC_SN 4 + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 2009.11.30 mtk02468: Moved these definitions to the right place */ +#if 0 +/* Block Ack Parameter Set field */ +#define BA_PARM_BA_POLICY BIT(1) +#define BA_PARM_TID BITS(2,5) +#define BA_PARM_BUFFER_SIZE BITS(6,15) +#endif + +#define BA_POLICY_IMMEDIATE BIT(1) + +/* Block Ack Starting Sequence Control field */ +#define BA_START_SEQ_CTL_FRAG_NUM BITS(0,3) +#define BA_START_SEQ_CTL_SSN BITS(4,15) + +/* BAR Control field */ +#define BAR_CONTROL_NO_ACK_POLICY BIT(0) +#define BAR_CONTROL_MULTI_TID BIT(1) +#define BAR_CONTROL_COMPRESSED_BA BIT(2) +#define BAR_CONTROL_TID_INFO BITS(12,15) +#define BAR_CONTROL_TID_INFO_OFFSET 12 + +/* TID Value */ +#define BAR_INFO_TID_VALUE BITS(12,15) + +#define BAR_COMPRESSED_VARIANT_FRAME_LEN (16 + 4) + +//3 /* --------------- IEEE 802.11 frame body fields --------------- */ +//3 Management frame body components (I): Fixed Fields. +/* 7.3.1.1 Authentication Algorithm Number field */ +#define AUTH_ALGORITHM_NUM_FIELD_LEN 2 + +#define AUTH_ALGORITHM_NUM_OPEN_SYSTEM 0 /* Open System */ +#define AUTH_ALGORITHM_NUM_SHARED_KEY 1 /* Shared Key */ +#define AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION 2 /* Fast BSS Transition */ + +/* 7.3.1.2 Authentication Transaction Sequence Number field */ +#define AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN 2 +#define AUTH_TRANSACTION_SEQ_1 1 +#define AUTH_TRANSACTION_SEQ_2 2 +#define AUTH_TRANSACTION_SEQ_3 3 +#define AUTH_TRANSACTION_SEQ_4 4 + +/* 7.3.1.3 Beacon Interval field */ +#define BEACON_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.4 Capability Information field */ +#define CAP_INFO_FIELD_LEN 2 +#define CAP_INFO_ESS BIT(0) +#define CAP_INFO_IBSS BIT(1) +#define CAP_INFO_BSS_TYPE (CAP_INFO_ESS | CAP_INFO_IBSS) +#define CAP_INFO_CF_POLLABLE BIT(2) +#define CAP_INFO_CF_POLL_REQ BIT(3) +#define CAP_INFO_CF (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) +#define CAP_INFO_PRIVACY BIT(4) +#define CAP_INFO_SHORT_PREAMBLE BIT(5) +#define CAP_INFO_PBCC BIT(6) +#define CAP_INFO_CH_AGILITY BIT(7) +#define CAP_INFO_SPEC_MGT BIT(8) +#define CAP_INFO_QOS BIT(9) +#define CAP_INFO_SHORT_SLOT_TIME BIT(10) +#define CAP_INFO_APSD BIT(11) +#define CAP_INFO_RESERVED BIT(12) +#define CAP_INFO_DSSS_OFDM BIT(13) +#define CAP_INFO_DELAYED_BLOCK_ACK BIT(14) +#define CAP_INFO_IMM_BLOCK_ACK BIT(15) +/* STA usage of CF-Pollable and CF-Poll Request subfields */ +/* STA: not CF-Pollable */ +#define CAP_CF_STA_NOT_POLLABLE 0x0000 +/* STA: CF-Pollable, not requesting on the CF-Polling list */ +#define CAP_CF_STA_NOT_ON_LIST CAP_INFO_CF_POLL_REQ +/* STA: CF-Pollable, requesting on the CF-Polling list */ +#define CAP_CF_STA_ON_LIST CAP_INFO_CF_POLLABLE +/* STA: CF-Pollable, requesting never to be polled */ +#define CAP_CF_STA_NEVER_POLLED (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) + +/* AP usage of CF-Pollable and CF-Poll Request subfields */ +/* AP: No point coordinator (PC) */ +#define CAP_CF_AP_NO_PC 0x0000 +/* AP: PC at AP for delivery only (no polling) */ +#define CAP_CF_AP_DELIVERY_ONLY CAP_INFO_CF_POLL_REQ +/* AP: PC at AP for delivery and polling */ +#define CAP_CF_AP_DELIVERY_POLLING CAP_INFO_CF_POLLABLE + +/* 7.3.1.5 Current AP Address field */ +#define CURR_AP_ADDR_FIELD_LEN MAC_ADDR_LEN + +/* 7.3.1.6 Listen Interval field */ +#define LISTEN_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.7 Reason Code field */ +#define REASON_CODE_FIELD_LEN 2 + +#define REASON_CODE_RESERVED 0 /* Reseved */ +#define REASON_CODE_UNSPECIFIED 1 /* Unspecified reason */ +#define REASON_CODE_PREV_AUTH_INVALID 2 /* Previous auth no longer valid */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 /* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 /* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 /* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_CLASS_2_ERR 6 /* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_3_ERR 7 /* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 /* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 /* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 /* Disassoc because the info in Power Capability is unacceptable */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 /* Disassoc because the info in Supported Channels is unacceptable */ +#define REASON_CODE_INVALID_INFO_ELEM 13 /* Invalid information element */ +#define REASON_CODE_MIC_FAILURE 14 /* MIC failure */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 /* 4-way handshake timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 /* Group key update timeout */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 /* Info element in 4-way handshake different from (Re-)associate request/Probe response/Beacon */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 /* Multicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 /* Unicast Cipher is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 /* AKMP is not valid */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 /* Unsupported RSNE version */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 /* Invalid RSNE Capabilities */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 /* IEEE 802.1X Authentication failed */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 /* Cipher suite rejected because of the security policy */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 /* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 /* Disassoc because QAP lacks sufficient bandwidth for this QSTA */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 /* Disassoc because of too many ACKs lost for AP transmissions and/or poor channel conditions */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 /* Disassoc because QSTA is transmitting outside the limits of its TXOPs */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ + +/* 7.3.1.8 AID field */ +#define AID_FIELD_LEN 2 +#define AID_MASK BITS(0,13) +#define AID_MSB BITS(14,15) +#define AID_MIN_VALUE 1 +#define AID_MAX_VALUE 2007 + +/* 7.3.1.9 Status Code field */ +#define STATUS_CODE_FIELD_LEN 2 + +#define STATUS_CODE_RESERVED 0 /* Reserved - Used by TX Auth */ +#define STATUS_CODE_SUCCESSFUL 0 /* Successful */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 /* Unspecified failure */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 /* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 /* Reassoc denied due to inability to confirm that assoc exists */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 /* Responding STA does not support the specified auth algorithm */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 /* Rx an auth frame with auth transaction seq num out of expected seq */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 /* Auth rejected due to timeout waiting for next frame in sequence */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 /* Assoc denied because AP is unable to handle additional assoc STAs */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 /* Assoc denied due to requesting STA not supporting all of basic rates */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 /* Assoc denied due to requesting STA not supporting short preamble */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 /* Assoc denied due to requesting STA not supporting channel agility */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 /* Assoc rejected because the info in Power Capability is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 /* Assoc rejected because the info in Supported Channels is unacceptable */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 /* Assoc denied due to requesting STA not supporting short slot time */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 /* Assoc denied due to requesting STA not supporting DSSS-OFDM */ +#if CFG_SUPPORT_802_11W +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 /* IEEE 802.11w, Assoc denied due to the MFP select policy */ +#endif +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 /* Assoc denied due to insufficient bandwidth to handle another QSTA */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 /* Assoc denied due to excessive frame loss rates and/or poor channel conditions */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 /* Assoc denied due to requesting STA not supporting QoS facility */ +#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 /* Request has not been successful as one or more parameters have invalid values */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 /* TS not created because request cannot be honored. Suggested TSPEC provided. */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 /* Invalid information element */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 /* Invalid group cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 /* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_AKMP 43 /* Invalid AKMP */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 /* Unsupported RSN information element version */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 /* Invalid RSN information element capabilities */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 /* Cipher suite rejected because of security policy */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 /* TS not created becasue request cannot be honored. Attempt to create a TS later. */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 /* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 /* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 /* Destination STA is not a QSTA */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 /* Association denied because the ListenInterval is too large */ + +/* proprietary definition of reserved field of Status Code */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 /* Join failure */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 /* Join timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 /* Authentication timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 /* (Re)Association timeout */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 /* CCX CCKM reassociation failure */ + + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 7.3.1.11 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +#define CATEGORY_QOS_ACTION 1 /* QoS action */ +#define CATEGORY_DLS_ACTION 2 /* Direct Link Protocol (DLP) action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 /* Block ack action */ +#define CATEGORY_PUBLIC_ACTION 4 /* Public action */ +#define CATEGORY_RM_ACTION 5 /* Radio measurement action */ +#define CATEGORY_HT_ACTION 7 +#if CFG_SUPPORT_802_11W +#define CATEGORY_SA_QUERT_ACTION 8 +#endif +#define CATEGORY_WNM_ACTION 10 /* 802.11v Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 /* 802.11v Wireless Network Management */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 /* WME management notification */ +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2,5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6,15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + + +//3 Management frame body components (II): Information Elements. +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID 0 /* SSID */ +#define ELEM_ID_SUP_RATES 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET 4 /* CF parameter set */ +#define ELEM_ID_TIM 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST 10 /* Request */ +#define ELEM_ID_BSS_LOAD 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP 33 /* Power capability */ +#define ELEM_ID_TPC_REQ 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT 35 /* TPC report */ +#define ELEM_ID_SUP_CHS 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT 39 /* Measurement report */ +#define ELEM_ID_QUIET 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO 42 /* ERP information */ +#define ELEM_ID_TS_DELAY 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP 46 /* QoS capability */ +#define ELEM_ID_RSN 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES 50 /* Extended supported rates */ +#if CFG_SUPPORT_802_11W +#define ELEM_ID_TIMEOUT_INTERVAL 56 /* 802.11w SA Timeout interval */ +#endif +#define ELEM_ID_HT_OP 61 /* HT Operation */ +#define ELEM_ID_SCO 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_20_40_BSS_COEXISTENCE 72 /* 20/40 BSS Coexistence */ +#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT 73 /* 20/40 BSS Intolerant Channel Report */ +#define ELEM_ID_OBSS_SCAN_PARAMS 74 /* Overlapping BSS Scan Parameters */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ +#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WFD ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_RESERVED 255 /* Reserved */ + + +/* 7.3.2.1 SSID element */ +#define ELEM_MAX_LEN_SSID 32 + +/* 7.3.2.2 Supported Rates */ +#define ELEM_MAX_LEN_SUP_RATES 8 + +/* 7.3.2.4 DS Parameter Set */ +#define ELEM_MAX_LEN_DS_PARAMETER_SET 1 + +/* 7.3.2.5 CF Parameter Set */ +#define ELEM_CF_PARM_LEN 8 + +/* 7.3.2.6 TIM */ +#define ELEM_MIX_LEN_TIM 4 +#define ELEM_MAX_LEN_TIM 254 + +/* 7.3.2.7 IBSS Parameter Set element */ +#define ELEM_MAX_LEN_IBSS_PARAMETER_SET 2 + +/* 7.3.2.8 Challenge Text element */ +#define ELEM_MIN_LEN_CHALLENGE_TEXT 1 +#define ELEM_MAX_LEN_CHALLENGE_TEXT 253 + +/* 7.3.2.9 Country Information element */ +/* Country IE should contain at least 3-bytes country code string and one subband triplet. */ +#define ELEM_MIN_LEN_COUNTRY_INFO 6 + +#define ELEM_ID_COUNTRY_INFO_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_SUBBAND_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_REGULATORY_TRIPLET_LEN_FIXED 3 + + +/* 7.3.2.13 ERP Information element */ +#define ELEM_MAX_LEN_ERP 1 +/* -- bits in the ERP Information element */ +#define ERP_INFO_NON_ERP_PRESENT BIT(0) /* NonERP_Present bit */ +#define ERP_INFO_USE_PROTECTION BIT(1) /* Use_Protection bit */ +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) /* Barker_Preamble_Mode bit */ + + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +/* 7.3.2.21 Measurement Request element */ +#define ELEM_RM_TYPE_BASIC_REQ 0 +#define ELEM_RM_TYPE_CCA_REQ 1 +#define ELEM_RM_TYPE_RPI_HISTOGRAM_REQ 2 +#define ELEM_RM_TYPE_CHNL_LOAD_REQ 3 +#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REQ 4 +#define ELEM_RM_TYPE_BEACON_REQ 5 +#define ELEM_RM_TYPE_FRAME_REQ 6 +#define ELEM_RM_TYPE_STA_STATISTICS_REQ 7 +#define ELEM_RM_TYPE_LCI_REQ 8 +#define ELEM_RM_TYPE_TS_REQ 9 +#define ELEM_RM_TYPE_MEASURE_PAUSE_REQ 255 + +/* 7.3.2.22 Measurement Report element */ +#define ELEM_RM_TYPE_BASIC_REPORT 0 +#define ELEM_RM_TYPE_CCA_REPORT 1 +#define ELEM_RM_TYPE_RPI_HISTOGRAM_REPORT 2 +#define ELEM_RM_TYPE_CHNL_LOAD_REPORT 3 +#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REPORT 4 +#define ELEM_RM_TYPE_BEACON_REPORT 5 +#define ELEM_RM_TYPE_FRAME_REPORT 6 +#define ELEM_RM_TYPE_STA_STATISTICS_REPORT 7 +#define ELEM_RM_TYPE_LCI_REPORT 8 +#define ELEM_RM_TYPE_TS_REPORT 9 + + +/* 7.3.2.25 RSN information element */ +#define ELEM_MAX_LEN_WPA 24 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200/* one pairwise, one AKM suite, one BKID */ + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_MAX_LEN_EXT_CAP (3 - ELEM_HDR_LEN) + +/* 7.3.2.30 TSPEC element */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) //WMM: 0 (Asynchronous TS of low-duty cycles) +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1,4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5,6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7,8) //WMM: Bit(7,8) = (1,0) = EDCA +#define TS_INFO_AGGREGATION_MASK BIT(9) //WMM: 0 +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11,13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14,15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.56 HT capabilities element */ +#define ELEM_MAX_LEN_HT_CAP (28 - ELEM_HDR_LEN) /* sizeof(IE_HT_CAP_T)-2 */ + +/* 7.3.2.56.2 HT capabilities Info field */ +#define HT_CAP_INFO_LDPC_CAP BIT(0) +#define HT_CAP_INFO_SUP_CHNL_WIDTH BIT(1) +#define HT_CAP_INFO_SM_POWER_SAVE BITS(2,3) +#define HT_CAP_INFO_HT_GF BIT(4) +#define HT_CAP_INFO_SHORT_GI_20M BIT(5) +#define HT_CAP_INFO_SHORT_GI_40M BIT(6) +#define HT_CAP_INFO_TX_STBC BIT(7) +#define HT_CAP_INFO_RX_STBC BITS(8,9) +#define HT_CAP_INFO_HT_DELAYED_BA BIT(10) +#define HT_CAP_INFO_MAX_AMSDU_LEN BIT(11) +#define HT_CAP_INFO_DSSS_CCK_IN_40M BIT(12) +#define HT_CAP_INFO_40M_INTOLERANT BIT(14) +#define HT_CAP_INFO_LSIG_TXOP_SUPPORT BIT(15) + +#define HT_CAP_INFO_RX_STBC_NO_SUPPORTED 0 +#define HT_CAP_INFO_RX_STBC_1_SS BIT(8) +#define HT_CAP_INFO_RX_STBC_2_SS BIT(9) +#define HT_CAP_INFO_RX_STBC_3_SS HT_CAP_INFO_RX_STBC + +/* 7.3.2.56.3 A-MPDU Parameters field */ +#define AMPDU_PARAM_MAX_AMPDU_LEN_EXP BITS(0,1) +#define AMPDU_PARAM_MIN_START_SPACING BITS(2,4) + +#define AMPDU_PARAM_MAX_AMPDU_LEN_8K 0 +#define AMPDU_PARAM_MAX_AMPDU_LEN_16K BIT(0) +#define AMPDU_PARAM_MAX_AMPDU_LEN_32K BIT(1) +#define AMPDU_PARAM_MAX_AMPDU_LEN_64K BITS(0,1) + +#define AMPDU_PARAM_MSS_NO_RESTRICIT 0 +#define AMPDU_PARAM_MSS_1_4_US BIT(2) +#define AMPDU_PARAM_MSS_1_2_US BIT(3) +#define AMPDU_PARAM_MSS_1_US BITS(2,3) +#define AMPDU_PARAM_MSS_2_US BIT(4) +#define AMPDU_PARAM_MSS_4_US (BIT(4) | BIT(2)) +#define AMPDU_PARAM_MSS_8_US (BIT(4) | BIT(3)) +#define AMPDU_PARAM_MSS_16_US BITS(2,4) + +/* 7.3.2.56.4 Supported MCS Set field (TX rate: octects 12~15) */ +#define SUP_MCS_TX_SET_DEFINED BIT(0) +#define SUP_MCS_TX_RX_SET_NOT_EQUAL BIT(1) +#define SUP_MCS_TX_MAX_NUM_SS BITS(2,3) +#define SUP_MCS_TX_UNEQUAL_MODULATION BIT(4) + +#define SUP_MCS_TX_MAX_NUM_1_SS 0 +#define SUP_MCS_TX_MAX_NUM_2_SS BIT(2) +#define SUP_MCS_TX_MAX_NUM_3_SS BIT(3) +#define SUP_MCS_TX_MAX_NUM_4_SS BITS(2,3) + +#define SUP_MCS_RX_BITMASK_OCTET_NUM 10 +#define SUP_MCS_RX_DEFAULT_HIGHEST_RATE 0 /* Not specify */ + +/* 7.3.2.56.5 HT Extended Capabilities field */ +#define HT_EXT_CAP_PCO BIT(0) +#define HT_EXT_CAP_PCO_TRANSITION_TIME BITS(1,2) +#define HT_EXT_CAP_MCS_FEEDBACK BITS(8,9) +#define HT_EXT_CAP_HTC_SUPPORT BIT(10) +#define HT_EXT_CAP_RD_RESPONDER BIT(11) + +#define HT_EXT_CAP_PCO_TRANS_TIME_NONE 0 +#define HT_EXT_CAP_PCO_TRANS_TIME_400US BIT(1) +#define HT_EXT_CAP_PCO_TRANS_TIME_1_5MS BIT(2) +#define HT_EXT_CAP_PCO_TRANS_TIME_5MS BITS(1,2) + +#define HT_EXT_CAP_MCS_FEEDBACK_NO_FB 0 +#define HT_EXT_CAP_MCS_FEEDBACK_UNSOLICITED BIT(9) +#define HT_EXT_CAP_MCS_FEEDBACK_BOTH BITS(8,9) + +/* 7.3.2.56.6 Transmit Beamforming Capabilities field */ + +/* 7.3.2.56.7 Antenna Selection Capability field */ +#define ASEL_CAP_CAPABLE BIT(0) +#define ASEL_CAP_CSI_FB_BY_TX_ASEL_CAPABLE BIT(1) +#define ASEL_CAP_ANT_INDICES_FB_BY_TX_ASEL_CAPABLE BIT(2) +#define ASEL_CAP_EXPLICIT_CSI_FB_CAPABLE BIT(3) +#define ASEL_CAP_ANT_INDICES_CAPABLE BIT(4) +#define ASEL_CAP_RX_ASEL_CAPABLE BIT(5) +#define ASEL_CAP_TX_SOUNDING_CAPABLE BIT(6) + +/* 7.3.2.57 HT Operation element */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) /* sizeof(IE_HT_OP_T)-2 */ + +#define HT_OP_INFO1_SCO BITS(0,1) +#define HT_OP_INFO1_STA_CHNL_WIDTH BIT(2) +#define HT_OP_INFO1_RIFS_MODE BIT(3) + +#define HT_OP_INFO2_HT_PROTECTION BITS(0,1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + + +//3 Management frame body components (III): 7.4 Action frame format details. +/* 7.4.1 Spectrum Measurement Action frame details */ +#define ACTION_MEASUREMENT_REQ 0 /* Spectrum measurement request */ +#define ACTION_MEASUREMENT_REPORT 1 /* Spectrum measurement report */ +#define ACTION_TPC_REQ 2 /* TPC request */ +#define ACTION_TPC_REPORT 3 /* TPC report */ +#define ACTION_CHNL_SWITCH 4 /* Channel Switch Announcement */ + +/* 7.4.2 QoS Action frame details */ +#define ACTION_ADDTS_REQ 0 /* ADDTS request */ +#define ACTION_ADDTS_RSP 1 /* ADDTS response */ +#define ACTION_DELTS 2 /* DELTS */ +#define ACTION_SCHEDULE 3 /* Schedule */ + +#define ACTION_ADDTS_REQ_FRAME_LEN (24+3+63) /* WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_RSP_FRAME_LEN (24+4+63) /* WMM Status Code: 1; WMM TSPEC IE: 63*/ + +/* 7.4.3 DLS Action frame details */ +#define ACTION_DLS_REQ 0 /* DLS request */ +#define ACTION_DLS_RSP 1 /* DLS response */ +#define ACTION_DLS_TEARDOWN 2 /* DLS teardown */ + +/* 7.4.4 Block ack Action frame details */ +#define ACTION_ADDBA_REQ 0 /* ADDBA request */ +#define ACTION_ADDBA_RSP 1 /* ADDBA response */ +#define ACTION_DELBA 2 /* DELBA */ + +#define ACTION_ADDBA_REQ_FRAME_LEN (24+9) +#define ACTION_ADDBA_RSP_FRAME_LEN (24+9) + +#define ACTION_DELBA_INITIATOR_MASK BIT(11) +#define ACTION_DELBA_TID_MASK BITS(12,15) +#define ACTION_DELBA_TID_OFFSET 12 +#define ACTION_DELBA_FRAME_LEN (24+6) + +/* 7.4.6 Radio Measurement Action frame details */ +#define ACTION_RM_REQ 0 /* Radio measurement request */ +#define ACTION_RM_REPORT 1 /* Radio measurement report */ +#define ACTION_LM_REQ 2 /* Link measurement request */ +#define ACTION_LM_REPORT 3 /* Link measurement report */ +#define ACTION_NEIGHBOR_REPORT_REQ 4 /* Neighbor report request */ +#define ACTION_NEIGHBOR_REPORT_RSP 5 /* Neighbor report response */ + +/* 7.4.7 Public Action frame details */ +#define ACTION_PUBLIC_20_40_COEXIST 0 /* 20/40 BSS coexistence */ + +#if CFG_SUPPORT_802_11W +/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ +#define ACTION_SA_QUERY_REQUEST 0 +#define ACTION_SA_QUERY_RESPONSE 1 + +#define ACTION_SA_QUERY_TR_ID_LEN 2 + +/* Timeout Interval Type */ +#define ACTION_SA_TIMEOUT_REASSOC_DEADLINE 1 +#define ACTION_SA_TIMEOUT_KEY_LIFETIME 2 +#define ACTION_SA_TIMEOUT_ASSOC_COMEBACK 3 +#endif + +/* 7.4.10.1 HT action frame details */ +#define ACTION_HT_NOTIFY_CHANNEL_WIDTH 0 /* Notify Channel Width */ +#define ACTION_HT_SM_POWER_SAVE 1 /* SM Power Save */ +#define ACTION_HT_PSMP 2 /* PSMP */ +#define ACTION_HT_SET_PCO_PHASE 3 /* Set PCO Phase */ +#define ACTION_HT_CSI 4 /* CSI */ +#define ACTION_HT_NON_COMPRESSED_BEAMFORM 5 /* Non-compressed Beamforming */ +#define ACTION_HT_COMPRESSED_BEAMFORM 6 /* Compressed Beamforming */ +#define ACTION_HT_ANT_SEL_INDICES_FB 7 /* Antenna Selection Indices Feedback */ + +/* 802.11v Wireless Network Management */ +#define ACTION_WNM_TIMING_MEASUREMENT_REQUEST 27 + +#define ACTION_UNPROTECTED_WNM_TIM 0 +#define ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT 1 + +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +//3 /* --------------- WFA frame body fields --------------- */ +#define VENDOR_OUI_WFA { 0x00, 0x50, 0xF2 } +#define VENDOR_OUI_WFA_SPECIFIC { 0x50, 0x6F, 0x9A } +#define VENDOR_OUI_TYPE_WPA 1 +#define VENDOR_OUI_TYPE_WMM 2 +#define VENDOR_OUI_TYPE_WPS 4 +#define VENDOR_OUI_TYPE_P2P 9 +#define VENDOR_OUI_TYPE_WFD 10 + +#define VENDOR_OUI_TYPE_LEN 4 /* Length of OUI and Type */ + +/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) fields for WMM in WFA IE */ +#define VERSION_WPA 0x0001 /* Little Endian Format */ +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 + +/* SUBTYPE(1 octet) for WMM */ +#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 /* WMM Spec version 1.1 */ +#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 +#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 + +/* VERSION(1 octet) for WMM */ +#define VERSION_WMM 0x01 /* WMM Spec version 1.1 */ + +/* WMM-2.1.6 QoS Control Field */ +#define WMM_QC_UP_MASK BITS(0,2) +#define WMM_QC_EOSP BIT(4) +#define WMM_QC_ACK_POLICY_MASK BITS(5, 6) +#define WMM_QC_ACK_POLICY_OFFSET 5 +#define WMM_QC_ACK_POLICY_ACKNOWLEDGE 0 +#define WMM_QC_ACK_POLICY_NOT_ACKNOWLEDGE (1 << WMM_QC_ACK_POLICY_OFFSET) + + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE 6 + + +//3 Control frame body +/* 7.2.1.7 BlockAckReq */ +#define CTRL_BAR_BAR_CONTROL_OFFSET 16 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +typedef struct _LLC_SNAP_HEADER_T { + UINT_8 ucDSAP; + UINT_8 ucSSAP; + UINT_8 ucControl; + UINT_8 aucCode[3]; + UINT_16 u2Type; +} __KAL_ATTRIB_PACKED__ LLC_SNAP_HEADER_T, *P_LLC_SNAP_HEADER_T; + +//3 MAC Header. +/* Ethernet Frame Header */ +typedef struct _ETH_FRAME_HEADER_T { + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_16 u2TypeLen; +} __KAL_ATTRIB_PACKED__ ETH_FRAME_HEADER_T, *P_ETH_FRAME_HEADER_T; + +/* Ethernet Frame Structure */ +typedef struct _ETH_FRAME_T { + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_16 u2TypeLen; + UINT_8 aucData[1]; +} __KAL_ATTRIB_PACKED__ ETH_FRAME_T, *P_ETH_FRAME_T; + + +/* IEEE 802.11 WLAN Frame Structure */ +/* WLAN MAC Header (without Address 4 and QoS Control fields) */ +typedef struct _WLAN_MAC_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_T, *P_WLAN_MAC_HEADER_T; + + +/* WLAN MAC Header (QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_QOS_T, *P_WLAN_MAC_HEADER_QOS_T; + + +/* WLAN MAC Header (HT Control fields included) */ +typedef struct _WLAN_MAC_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_HT_T, *P_WLAN_MAC_HEADER_HT_T; + + +/* WLAN MAC Header (Address 4 included) */ +typedef struct _WLAN_MAC_HEADER_A4_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_T, *P_WLAN_MAC_HEADER_A4_T; + + +/* WLAN MAC Header (Address 4 and QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_A4_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_QOS_T, *P_WLAN_MAC_HEADER_A4_QOS_T; + + +typedef struct _WLAN_MAC_HEADER_A4_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_HT_T, *P_WLAN_MAC_HEADER_A4_HT_T; + + +/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ +typedef struct _WLAN_MAC_MGMT_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2Duration; + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_T, *P_WLAN_MAC_MGMT_HEADER_T; + + +/* WLAN MAC Header for Management Frame (HT Control fields included) */ +typedef struct _WLAN_MAC_MGMT_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_HT_T, *P_WLAN_MAC_MGMT_HEADER_HT_T; + +//3 WLAN CONTROL Frame +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +typedef struct _CTRL_PSPOLL_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2AID; /* AID */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_8 aucTA[MAC_ADDR_LEN]; /* TA */ +} __KAL_ATTRIB_PACKED__ CTRL_PSPOLL_FRAME_T, *P_CTRL_PSPOLL_FRAME_T; + + +/* BAR */ +typedef struct _CTRL_BAR_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* RA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* TA */ + UINT_16 u2BarControl; + UINT_8 aucBarInfo[2]; /* Variable size */ +} __KAL_ATTRIB_PACKED__ CTRL_BAR_FRAME_T, *P_CTRL_BAR_FRAME_T; + +//3 WLAN Management Frame. +/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ +typedef struct _WLAN_BEACON_FRAME_T { + /* Beacon header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_T, *P_WLAN_BEACON_FRAME_T; + +typedef struct _WLAN_BEACON_FRAME_BODY_T { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_BODY_T, *P_WLAN_BEACON_FRAME_BODY_T; + + +/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ +typedef struct _WLAN_DISASSOC_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Disassociation frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DISASSOC_FRAME_T, *P_WLAN_DISASSOC_FRAME_T; + + +/* 7.2.3.4 WLAN Management Frame - Association Request frame */ +typedef struct _WLAN_ASSOC_REQ_FRAME_T { + /* Association Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_REQ_FRAME_T, *P_WLAN_ASSOC_REQ_FRAME_T; + + +/* 7.2.3.5 WLAN Management Frame - Association Response frame */ +typedef struct _WLAN_ASSOC_RSP_FRAME_T { + /* Association Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Response frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2StatusCode; /* Status code */ + UINT_16 u2AssocId; /* Association ID */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + supported rates, and etc. */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_RSP_FRAME_T, *P_WLAN_ASSOC_RSP_FRAME_T; + + +/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ +typedef struct _WLAN_REASSOC_REQ_FRAME_T { + /* Reassociation Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Reassociation Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_REASSOC_REQ_FRAME_T, *P_WLAN_REASSOC_REQ_FRAME_T; + + +/* 7.2.3.7 WLAN Management Frame - Reassociation Response frame + (the same as Association Response frame) */ +typedef WLAN_ASSOC_RSP_FRAME_T WLAN_REASSOC_RSP_FRAME_T, *P_WLAN_REASSOC_RSP_FRAME_T; + +/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ +typedef WLAN_BEACON_FRAME_T WLAN_PROBE_RSP_FRAME_T, *P_WLAN_PROBE_RSP_FRAME_T; + +/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ +typedef struct _WLAN_AUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Authentication frame body */ + UINT_16 u2AuthAlgNum; /* Authentication algorithm number */ + UINT_16 u2AuthTransSeqNo; /* Authentication transaction sequence number */ + UINT_16 u2StatusCode; /* Status code */ + UINT_8 aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ +} __KAL_ATTRIB_PACKED__ WLAN_AUTH_FRAME_T, *P_WLAN_AUTH_FRAME_T; + + +/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ +typedef struct _WLAN_DEAUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Deauthentication frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DEAUTH_FRAME_T, *P_WLAN_DEAUTH_FRAME_T; + + + +//3 Information Elements. +/* 7.3.2 Generic element format */ +typedef struct _IE_HDR_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucInfo[1]; +} __KAL_ATTRIB_PACKED__ IE_HDR_T, *P_IE_HDR_T; + +/* 7.3.2.1 SSID element */ +typedef struct _IE_SSID_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; +} __KAL_ATTRIB_PACKED__ IE_SSID_T, *P_IE_SSID_T; + +/* 7.3.2.2 Supported Rates element */ +typedef struct _IE_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_RATE_T, *P_IE_SUPPORTED_RATE_T; + +/* 7.3.2.4 DS Parameter Set element */ +typedef struct _IE_DS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCurrChnl; +} __KAL_ATTRIB_PACKED__ IE_DS_PARAM_SET_T, *P_IE_DS_PARAM_SET_T; + + +/* 7.3.2.5 CF Parameter Set element */ +typedef struct _IE_CF_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCFPCount; + UINT_8 ucCFPPeriod; + UINT_16 u2CFPMaxDur; + UINT_16 u2DurRemaining; +} __KAL_ATTRIB_PACKED__ IE_CF_PARAM_SET_T, *P_IE_CF_PARAM_SET_T; + + +/* 7.3.2.6 TIM */ +typedef struct _IE_TIM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucDTIMCount; + UINT_8 ucDTIMPeriod; + UINT_8 ucBitmapControl; + UINT_8 aucPartialVirtualMap[1]; +} __KAL_ATTRIB_PACKED__ IE_TIM_T, *P_IE_TIM_T; + +/* 7.3.2.7 IBSS Parameter Set element */ +typedef struct _IE_IBSS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ATIMWindow; +} __KAL_ATTRIB_PACKED__ IE_IBSS_PARAM_SET_T, *P_IE_IBSS_PARAM_SET_T; + +/* 7.3.2.8 Challenge Text element */ +typedef struct _IE_CHALLENGE_TEXT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; +} __KAL_ATTRIB_PACKED__ IE_CHALLENGE_TEXT_T, *P_IE_CHALLENGE_TEXT_T; + +/* 7.3.2.9 Country information element */ +#if CFG_SUPPORT_802_11D +/*! \brief COUNTRY_INFO_TRIPLET is defined for the COUNTRY_INFO_ELEM structure. */ +typedef struct _COUNTRY_INFO_TRIPLET_T { + UINT_8 ucParam1; /*!< If param1 >= 201, this triplet is referred to as + Regulatory Triplet in 802_11J. */ + UINT_8 ucParam2; + UINT_8 ucParam3; +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_TRIPLET_T, *P_COUNTRY_INFO_TRIPLET_T; + +typedef struct _COUNTRY_INFO_SUBBAND_TRIPLET_T { + UINT_8 ucFirstChnlNum; /*!< First Channel Number */ + UINT_8 ucNumOfChnl; /*!< Number of Channels */ + INT_8 cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_SUBBAND_TRIPLET_T, *P_COUNTRY_INFO_SUBBAND_TRIPLET_T; + +typedef struct _COUNTRY_INFO_REGULATORY_TRIPLET_T { + UINT_8 ucRegExtId; /*!< Regulatory Extension Identifier, should + be greater than or equal to 201 */ + UINT_8 ucRegClass; /*!< Regulatory Class */ + UINT_8 ucCoverageClass; /*!< Coverage Class, unsigned 1-octet value 0~31 + , 32~255 reserved */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_REGULATORY_TRIPLET_T, *P_COUNTRY_INFO_REGULATORY_TRIPLET_T; + +typedef struct _IE_COUNTRY_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCountryStr[3]; + COUNTRY_INFO_SUBBAND_TRIPLET_T arCountryStr[1]; +} __KAL_ATTRIB_PACKED__ IE_COUNTRY_T, *P_IE_COUNTRY_T; +#endif /* CFG_SUPPORT_802_11D */ + +/* 7.3.2.13 ERP element */ +typedef struct _IE_ERP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucERP; +} __KAL_ATTRIB_PACKED__ IE_ERP_T, *P_IE_ERP_T; + +/* 7.3.2.14 Extended Supported Rates element */ +typedef struct _IE_EXT_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_EXT_SUPPORTED_RATE_T, *P_IE_EXT_SUPPORTED_RATE_T; + +/* 7.3.2.15 Power Constraint element */ +typedef struct _IE_POWER_CONSTRAINT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucLocalPowerConstraint; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CONSTRAINT_T, *P_IE_POWER_CONSTRAINT_T; + +/* 7.3.2.16 Power Capability element */ +typedef struct _IE_POWER_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cMinTxPowerCap; /* Unit: dBm */ + INT_8 cMaxTxPowerCap; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CAP_T, *P_IE_POWER_CAP_T; + +/* 7.3.2.17 TPC request element */ +typedef struct _IE_TPC_REQ_T { + UINT_8 ucId; + UINT_8 ucLength; +} __KAL_ATTRIB_PACKED__ IE_TPC_REQ_T, *P_IE_TPC_REQ_T; + +/* 7.3.2.18 TPC report element */ +typedef struct _IE_TPC_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cTxPower; /* Unit: dBm */ + INT_8 cLinkMargin; /* Unit: dB */ +} __KAL_ATTRIB_PACKED__ IE_TPC_REPORT_T, *P_IE_TPC_REPORT_T; + +/* 7.3.2.20 Channel Switch Announcement element */ +typedef struct _IE_CHNL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucSwitchMode; + UINT_8 ucNewChannel; + UINT_8 ucSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_CHNL_SWITCH_T, *P_IE_CHNL_SWITCH_T; + +/* 7.3.2.21 Measurement Request element */ +typedef struct _IE_MEASUREMENT_REQ_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucToken; + UINT_8 ucRequestMode; + UINT_8 ucMeasurementType; + UINT_8 aucRequestFields[1]; +} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REQ_T, *P_IE_MEASUREMENT_REQ_T; + +typedef struct _SM_BASIC_REQ_T { + UINT_8 ucChannel; + UINT_32 au4StartTime[2]; + UINT_16 u2Duration; +} __KAL_ATTRIB_PACKED__ SM_BASIC_REQ_T, *P_SM_BASIC_REQ_T; + +/* SM_COMMON_REQ_T is not specified in Spec. Use it as common structure of SM */ +typedef SM_BASIC_REQ_T SM_REQ_COMMON_T, *P_SM_REQ_COMMON_T; +typedef SM_BASIC_REQ_T SM_CCA_REQ_T, *P_SM_CCA_REQ_T; +typedef SM_BASIC_REQ_T SM_RPI_HISTOGRAM_REQ_T, *P_SM_RPI_HISTOGRAM_REQ_T; + +typedef struct _RM_CHNL_LOAD_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REQ_T, *P_RM_CHNL_LOAD_REQ_T; + +typedef RM_CHNL_LOAD_REQ_T \ + RM_NOISE_HISTOGRAM_REQ_T, *P_RM_NOISE_HISTOGRAM_REQ_T; + +typedef struct _RM_BCN_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucMeasurementMode; + UINT_8 aucBssid[6]; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_BCN_REQ_T, *P_RM_BCN_REQ_T; + +typedef struct _RM_FRAME_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucFrameReqType; + UINT_8 aucMacAddr[6]; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_FRAME_REQ_T, *P_RM_FRAME_REQ_T; + +typedef struct _RM_STA_STATS_REQ_T { + UINT_8 aucPeerMacAddr[6]; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucGroupID; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_STA_STATS_REQ_T, *P_RM_STA_STATS_REQ_T; + +typedef struct _RM_LCI_REQ_T { + UINT_8 ucLocationSubject; + UINT_8 ucLatitudeResolution; + UINT_8 ucLongitudeResolution; + UINT_8 ucAltitudeResolution; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_LCI_REQ_T, *P_RM_LCI_REQ_T; + +typedef struct _RM_TS_MEASURE_REQ_T { + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 aucPeerStaAddr[6]; + UINT_8 ucTrafficID; + UINT_8 ucBin0Range; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_TS_MEASURE_REQ_T, *P_RM_TS_MEASURE_REQ_T; + +typedef struct _RM_MEASURE_PAUSE_REQ_T { + UINT_16 u2PauseTime; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_MEASURE_PAUSE_REQ_T, *P_RM_MEASURE_PAUSE_REQ_T; + +/* 7.3.2.22 Measurement Report element */ +typedef struct _IE_MEASUREMENT_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucToken; + UINT_8 ucReportMode; + UINT_8 ucMeasurementType; + UINT_8 aucReportFields[1]; +} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REPORT_T, *P_IE_MEASUREMENT_REPORT_T; + +typedef struct _SM_BASIC_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucMap; +} __KAL_ATTRIB_PACKED__ SM_BASIC_REPORT_T, *P_SM_BASIC_REPORT_T; + +typedef struct _SM_CCA_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucCcaBusyFraction; +} __KAL_ATTRIB_PACKED__ SM_CCA_REPORT_T, *P_SM_CCA_REPORT_T; + +typedef struct _SM_RPI_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 aucRPI[8]; +} __KAL_ATTRIB_PACKED__ SM_RPI_REPORT_T, *P_SM_RPI_REPORT_T; + +typedef struct _RM_CHNL_LOAD_REPORT_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucChnlLoad; +} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REPORT_T, *P_RM_CHNL_LOAD_REPORT_T; + +typedef struct _RM_IPI_REPORT_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucAntennaId; + INT_8 cANPI; + UINT_8 aucIPI[11]; +} __KAL_ATTRIB_PACKED__ RM_IPI_REPORT_T, *P_RM_IPI_REPORT_T; + +/* 7.3.2.23 Quiet element */ +typedef struct _IE_QUIET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCount; + UINT_8 ucPeriod; + UINT_16 u2Duration; + UINT_16 u2Offset; +} __KAL_ATTRIB_PACKED__ IE_QUIET_T, *P_IE_QUIET_T; + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_EXT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCapabilities[1]; +} __KAL_ATTRIB_PACKED__ IE_EXT_CAP_T, *P_EXT_CAP_T; + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_RRM_ENABLED_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCap[5]; +} __KAL_ATTRIB_PACKED__ IE_RRM_ENABLED_CAP_T, *P_IE_RRM_ENABLED_CAP_T; + +/* 7.3.2.56 HT Capabilities element */ +typedef struct _SUP_MCS_SET_FIELD { + UINT_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; +} __KAL_ATTRIB_PACKED__ SUP_MCS_SET_FIELD, *P_SUP_MCS_SET_FIELD; + +typedef struct _IE_HT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2HtCapInfo; + UINT_8 ucAmpduParam; + SUP_MCS_SET_FIELD rSupMcsSet; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; +} __KAL_ATTRIB_PACKED__ IE_HT_CAP_T, *P_IE_HT_CAP_T; + +/* 7.3.2.57 HT Operation element */ +typedef struct _IE_HT_OP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucPrimaryChannel; + UINT_8 ucInfo1; + UINT_16 u2Info2; + UINT_16 u2Info3; + UINT_8 aucBasicMcsSet[16]; +} __KAL_ATTRIB_PACKED__ IE_HT_OP_T, *P_IE_HT_OP_T; + +/* 7.3.2.25 RSN Information element format */ +typedef struct _RSN_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ RSN_INFO_ELEM_T, *P_RSN_INFO_ELEM_T; + +/* 7.3.2.26 WPA Information element format */ +typedef struct _WPA_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UCHAR aucOui[3]; + UCHAR ucOuiType; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ WPA_INFO_ELEM_T, *P_WPA_INFO_ELEM_T; + +/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ +typedef struct _IE_INTOLERANT_CHNL_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucRegulatoryClass; + UINT_8 aucChannelList[1]; +} __KAL_ATTRIB_PACKED__ IE_INTOLERANT_CHNL_REPORT_T, *P_IE_INTOLERANT_CHNL_REPORT_T; + +/* 7.3.2.59 OBSS Scan Parameters element */ +typedef struct _IE_OBSS_SCAN_PARAM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ScanPassiveDwell; + UINT_16 u2ScanActiveDwell; + UINT_16 u2TriggerScanInterval; + UINT_16 u2ScanPassiveTotalPerChnl; + UINT_16 u2ScanActiveTotalPerChnl; + UINT_16 u2WidthTransDelayFactor; + UINT_16 u2ScanActivityThres; +} __KAL_ATTRIB_PACKED__ IE_OBSS_SCAN_PARAM_T, *P_IE_OBSS_SCAN_PARAM_T; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_20_40_COEXIST_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucData; +} __KAL_ATTRIB_PACKED__ IE_20_40_COEXIST_T, *P_IE_20_40_COEXIST_T; + + +//3 7.4 Action Frame. +/* 7.4 Action frame format */ +typedef struct _WLAN_ACTION_FRAME { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucActionDetails[1]; /* Action details */ +} __KAL_ATTRIB_PACKED__ WLAN_ACTION_FRAME, *P_WLAN_ACTION_FRAME; + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +typedef struct _ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_SM_REQ_FRAME, *P_ACTION_SM_REQ_FRAME; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ +typedef ACTION_SM_REQ_FRAME ACTION_SM_REPORT_FRAME, *P_ACTION_SM_REPORT_FRAME; + +/* 7.4.2.1 ADDTS Request frame format */ +typedef struct _ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; + + +/* 7.4.2.2 ADDTS Response frame format */ +typedef struct _ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; + + +/* 7.4.2.3 DELTS frame format */ +typedef struct _ACTION_DELTS_FRAME { + /* DELTS MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; + + +/* 7.4.4.1 ADDBA Request frame format */ +typedef struct _ACTION_ADDBA_REQ_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; + UINT_8 aucBAStartSeqCtrl[2]; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_FRAME_T, *P_ACTION_ADDBA_REQ_FRAME_T; + +typedef struct _ACTION_ADDBA_REQ_BODY_T{ + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_BODY_T, *P_ACTION_ADDBA_REQ_BODY_T; + +/* 7.4.4.2 ADDBA Response frame format */ +typedef struct _ACTION_ADDBA_RSP_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucStatusCode[2]; + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_FRAME_T, *P_ACTION_ADDBA_RSP_FRAME_T; + +typedef struct _ACTION_ADDBA_RSP_BODY_T { + UINT_16 u2StatusCode; + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_BODY_T, *P_ACTION_ADDBA_RSP_BODY_T; + +/* 7.4.4.3 DELBA frame format */ +typedef struct _ACTION_DELBA_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_16 u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ + UINT_16 u2ReasonCode; /* 7.3.1.7 */ +} __KAL_ATTRIB_PACKED__ ACTION_DELBA_FRAME_T, *P_ACTION_DELBA_FRAME_T; + +/* 7.4.6.1 Radio Measurement Request frame format */ +typedef struct _ACTION_RM_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_16 u2Repetitions; /* Number of repetitions */ + UINT_8 aucInfoElem[1]; /* Measurement Request elements, such as + channel load request, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REQ_FRAME, *P_ACTION_RM_REQ_FRAME; + +/* 7.4.6.2 Radio Measurement Report frame format */ +typedef struct _ACTION_RM_REPORT_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Report frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Measurement Report elements, such as + channel load report, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REPORT_FRAME, *P_ACTION_RM_REPORT_FRAME; + +/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ +typedef struct _ACTION_20_40_COEXIST_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + IE_20_40_COEXIST_T rBssCoexist;/* 20/40 BSS coexistence element */ + IE_INTOLERANT_CHNL_REPORT_T rChnlReport;/* Intolerant channel report */ + +} __KAL_ATTRIB_PACKED__ ACTION_20_40_COEXIST_FRAME, *P_ACTION_20_40_COEXIST_FRAME; + + +#if CFG_SUPPORT_802_11W +/* 7.4.9 SA Query Management frame format */ +typedef struct _ACTION_SA_QUERY_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ + +} __KAL_ATTRIB_PACKED__ ACTION_SA_QUERY_FRAME, *P_ACTION_SA_QUERY_FRAME; +#endif + +/* 7.4.10 Notify Channel Width Management frame format */ +typedef struct _ACTION_NOTIFY_CHNL_WIDTH_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucChannelWidth; /* Channel Width */ +} __KAL_ATTRIB_PACKED__ ACTION_NOTIFY_CHNL_WIDTH_FRAME, *P_ACTION_NOTIFY_CHNL_WIDTH_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement Request */ +typedef struct _ACTION_WNM_TIMING_MEAS_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Request Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucTrigger; /* Trigger */ +} __KAL_ATTRIB_PACKED__ ACTION_WNM_TIMING_MEAS_REQ_FRAME, *P_ACTION_WNM_TIMING_MEAS_REQ_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement */ +typedef struct _ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ + UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ + UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ + UINT_8 ucMaxToDErr; /* Maximum of ToD Error [10ns] */ + UINT_8 ucMaxToAErr; /* Maximum of ToA Error [10ns] */ +} __KAL_ATTRIB_PACKED__ ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME, *P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME; + +//3 Information Elements from WFA. +typedef struct _IE_WFA_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 ucOuiType; + UINT_8 aucOuiSubTypeVersion[2]; + /*!< Please be noted. WPA defines a 16 bit field version + instead of one subtype field and one version field*/ +} __KAL_ATTRIB_PACKED__ IE_WFA_T, *P_IE_WFA_T; + +/* WAPI Information element format */ +typedef struct _WAPI_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_16 u2AuthKeyMgtSuiteCount; + UCHAR aucAuthKeyMgtSuite1[4]; +} __KAL_ATTRIB_PACKED__ WAPI_INFO_ELEM_T, *P_WAPI_INFO_ELEM_T; + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Convert the ECWmin(max) to CWmin(max) */ +#define ECW_TO_CW(_ECW) ((1 << (_ECW)) - 1) + +/* Convert the RCPI to dBm */ +#define RCPI_TO_dBm(_rcpi) \ + ((PARAM_RSSI)(((_rcpi) > RCPI_HIGH_BOUND ? RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) + +/* Convert the dBm to RCPI */ +#define dBm_TO_RCPI(_dbm) \ + (RCPI)( ( (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ + ( (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ + (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) ) ) + +/* Convert an unsigned char pointer to an information element pointer */ +#define IE_ID(fp) (((P_IE_HDR_T) fp)->ucId) +#define IE_LEN(fp) (((P_IE_HDR_T) fp)->ucLength) +#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) + +#define SSID_IE(fp) ((P_IE_SSID_T) fp) + +#define SUP_RATES_IE(fp) ((P_IE_SUPPORTED_RATE_T) fp) + +#define DS_PARAM_IE(fp) ((P_IE_DS_PARAM_SET_T) fp) + +#define TIM_IE(fp) ((P_IE_TIM_T) fp) + +#define IBSS_PARAM_IE(fp) ((P_IE_IBSS_PARAM_SET_T) fp) + +#define ERP_INFO_IE(fp) ((P_IE_ERP_T) fp) + +#define EXT_SUP_RATES_IE(fp) ((P_IE_EXT_SUPPORTED_RATE_T) fp) + +#define WFA_IE(fp) ((P_IE_WFA_T) fp) + +#if CFG_SUPPORT_802_11D +#define COUNTRY_IE(fp) ((P_IE_COUNTRY_T) fp) +#endif + +#define EXT_CAP_IE(fp) ((P_EXT_CAP_T) fp) + +#define HT_CAP_IE(fp) ((P_IE_HT_CAP_T) fp) + +#define HT_OP_IE(fp) ((P_IE_HT_OP_T) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) + +#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) + + + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) ( ((PUINT_8)(_pucDestAddr))[0] & BIT(0) )) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) !( ((PUINT_8)(_pucDestAddr))[0] & BIT(0) )) + +/* The macro to copy the MAC address */ +#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) + +/* The macro to check if two MAC addresses are equal */ +#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check if two MAC addresses are not equal */ +#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + + +/* The macro to check whether two SSIDs are equal */ +#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ + (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ + ((ucSsidLen1) == (ucSsidLen2)) && \ + !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to check whether two SSIDs are equal */ +#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ + (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ + ((ucSsidLen1) != (ucSsidLen2)) || \ + kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ +#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ + do { \ + ucDestSsidLen = ucSrcSsidLen; \ + if (ucSrcSsidLen) { \ + ASSERT(ucSrcSsidLen <= ELEM_MAX_LEN_SSID); \ + kalMemCopy(pucDestSsid, pucSrcSsid, ((ucSrcSsidLen > ELEM_MAX_LEN_SSID) ? ELEM_MAX_LEN_SSID : ucSrcSsidLen)); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((PUINT_8)pucDestIE, \ + (PUINT_8)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))) ; \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAC_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h new file mode 100755 index 000000000000..3f2eacd3a1a2 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h @@ -0,0 +1,286 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mt6620_reg.h#1 $ +*/ + +/*! \file "mt6620_reg.h" + \brief The common register definition of mt6620 + + N/A +*/ + + + +/* +** $Log: mt6620_reg.h $ + * + * 01 31 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * Print firmware ASSERT info at Android kernel log, driver side + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-12-10 16:44:18 GMT mtk02752 +** remove 5921 definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-09 22:56:32 GMT mtk01084 +** modify HW register definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-04 14:11:04 GMT mtk01084 +** modify default IER bits +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:52:32 GMT mtk01084 +** modify data struture +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:08:20 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:53 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-09-09 17:26:11 GMT mtk01084 +** add CFG_TEST_WITH_MT5921 +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-18 20:59:57 GMT mtk01426 +** Update WHIER_DEFAULT value +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-07 16:57:36 GMT mtk01426 +** Update CHIP ID to 0x6620, and WHLPCR bit definition +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:34:57 GMT mtk01461 +** Add read WTSR and fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-24 09:46:52 GMT mtk01084 +** fix LINT error +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:32:24 GMT mtk01461 +** Define constants for TX PATH +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:54:10 GMT mtk01426 +** Add WHCR_MAX_HIF_RX_AGG_LEN_OFFSET definition +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:29 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _MT6620_REG_H +#define _MT6620_REG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +//1 MT6620 MCR Definition + +//2 Host Interface + +//4 CHIP ID Register +#define MCR_WCIR 0x0000 + +//4 HIF Low Power Control Register +#define MCR_WHLPCR 0x0004 +//#define MCR_WHLPCR_BYTE1 0x0005 + + +//4 Control Status Register +#define MCR_WSDIOCSR 0x0008 +#define MCR_WSPICSR 0x0008 + +//4 HIF Control Register +#define MCR_WHCR 0x000C + +//4 HIF Interrupt Status Register +#define MCR_WHISR 0x0010 + +//4 HIF Interrupt Enable Register +#define MCR_WHIER 0x0014 + +//4 Abnormal Status Register +#define MCR_WASR 0x0018 + +//4 WLAN Software Interrupt Control Register +#define MCR_WSICR 0x001C + +//4 WLAN TX Status Register +#define MCR_WTSR0 0x0020 + +//4 WLAN TX Status Register +#define MCR_WTSR1 0x0024 + +//4 WLAN TX Data Register 0 +#define MCR_WTDR0 0x0028 + +//4 WLAN TX Data Register 1 +#define MCR_WTDR1 0x002C + +//4 WLAN RX Data Register 0 +#define MCR_WRDR0 0x0030 + +//4 WLAN RX Data Register 1 +#define MCR_WRDR1 0x0034 + +//4 Host to Device Send Mailbox 0 Register +#define MCR_H2DSM0R 0x0038 + +//4 Host to Device Send Mailbox 1 Register +#define MCR_H2DSM1R 0x003c + +//4 Device to Host Receive Mailbox 0 Register +#define MCR_D2HRM0R 0x0040 + +//4 Device to Host Receive Mailbox 1 Register +#define MCR_D2HRM1R 0x0044 + +//4 WLAN RX Packet Length Register +#define MCR_WRPLR 0x0048 + + + + +//temp //#if CFG_SDIO_INTR_ENHANCE +typedef struct _ENHANCE_MODE_DATA_STRUCT_T { + UINT_32 u4WHISR; + union { + struct { + UINT_8 ucTQ0Cnt; + UINT_8 ucTQ1Cnt; + UINT_8 ucTQ2Cnt; + UINT_8 ucTQ3Cnt; + UINT_8 ucTQ4Cnt; + UINT_8 ucTQ5Cnt; + UINT_16 u2Rsrv; + } u; + UINT_32 au4WTSR[2]; + } rTxInfo; + union { + struct { + UINT_16 u2NumValidRx0Len; + UINT_16 u2NumValidRx1Len; + UINT_16 au2Rx0Len[16]; + UINT_16 au2Rx1Len[16]; + } u; + UINT_32 au4RxStatusRaw[17]; + } rRxInfo; + UINT_32 u4RcvMailbox0; + UINT_32 u4RcvMailbox1; +} ENHANCE_MODE_DATA_STRUCT_T, *P_ENHANCE_MODE_DATA_STRUCT_T; +// #endif /* ENHANCE_MODE_DATA_STRUCT_T */ + + +//2 Definition in each register +//3 WCIR 0x0000 +#define WCIR_WLAN_READY BIT(21) +#define WCIR_POR_INDICATOR BIT(20) +#define WCIR_REVISION_ID BITS(16,19) +#define WCIR_CHIP_ID BITS(0,15) + +#define MTK_CHIP_REV 0x00006620 +#define MTK_CHIP_MP_REVERSION_ID 0x0 + +//3 WHLPCR 0x0004 +#define WHLPCR_FW_OWN_REQ_CLR BIT(9) +#define WHLPCR_FW_OWN_REQ_SET BIT(8) +#define WHLPCR_IS_DRIVER_OWN BIT(8) +#define WHLPCR_INT_EN_CLR BIT(1) +#define WHLPCR_INT_EN_SET BIT(0) + +//3 WSDIOCSR 0x0008 +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +//3 WSPICSR 0x0008 +#define WCSR_SPI_MODE_SEL BITS(3,4) +#define WCSR_SPI_ENDIAN_BIG BIT(2) +#define WCSR_SPI_INT_OUT_MODE BIT(1) +#define WCSR_SPI_DATA_OUT_MODE BIT(0) + +//3 WHCR 0x000C +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(4,7) +#define WHCR_W_MAILBOX_RD_CLR_EN BIT(2) +#define WHCR_W_INT_CLR_CTRL BIT(1) +#define WHCR_MCU_DBG_EN BIT(0) +#define WHCR_OFFSET_MAX_HIF_RX_LEN_NUM 4 + +//3 WHISR 0x0010 +#define WHISR_D2H_SW_INT BITS(8,31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_FW_INT_INDICATOR BIT(7) +#define WHISR_FW_OWN_BACK_INT BIT(4) +#define WHISR_ABNORMAL_INT BIT(3) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + + +//3 WHIER 0x0014 +#define WHIER_D2H_SW_INT BITS(8,31) +#define WHIER_FW_INT_INDICATOR_EN BIT(7) +#define WHIER_FW_OWN_BACK_INT_EN BIT(4) +#define WHIER_ABNORMAL_INT_EN BIT(3) +#define WHIER_RX1_DONE_INT_EN BIT(2) +#define WHIER_RX0_DONE_INT_EN BIT(1) +#define WHIER_TX_DONE_INT_EN BIT(0) +#define WHIER_DEFAULT (WHIER_RX0_DONE_INT_EN | \ + WHIER_RX1_DONE_INT_EN | \ + WHIER_TX_DONE_INT_EN | \ + WHIER_ABNORMAL_INT_EN | \ + WHIER_D2H_SW_INT \ + ) + + +//3 WASR 0x0018 +#define WASR_FW_OWN_INVALID_ACCESS BIT(4) +#define WASR_RX1_UNDER_FLOW BIT(3) +#define WASR_RX0_UNDER_FLOW BIT(2) +#define WASR_TX1_OVER_FLOW BIT(1) +#define WASR_TX0_OVER_FLOW BIT(0) + + +//3 WSICR 0x001C +#define WSICR_H2D_SW_INT_SET BITS(16,31) + + +//3 WTSR0 0x0044 +#define WRPLR_RX1_PACKET_LENGTH BITS(16,31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0,15) + +#endif /* _MT6620_REG_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h new file mode 100755 index 000000000000..64631384d9dc --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h @@ -0,0 +1,724 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic.h#1 $ +*/ + +/*! \file "nic.h" + \brief The declaration of nic functions + + Detail description. +*/ + + + +/* +** $Log: nic.h $ + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to the AP.. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always process TX interrupt first then RX interrupt. + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-10-13 21:58:58 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-24 21:12:55 GMT mtk01104 +** Add function prototype nicRestoreSpiDefMode() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:54 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:32 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_H +#define _NIC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +struct _REG_ENTRY_T { + UINT_32 u4Offset; + UINT_32 u4Value; +}; + +struct _TABLE_ENTRY_T { + P_REG_ENTRY_T pu4TablePtr; + UINT_16 u2Size; +}; + +/*! INT status to event map */ +typedef struct _INT_EVENT_MAP_T { + UINT_32 u4Int; + UINT_32 u4Event; +} INT_EVENT_MAP_T, *P_INT_EVENT_MAP_T; + + +enum ENUM_INT_EVENT_T { + INT_EVENT_ABNORMAL, + INT_EVENT_SW_INT, + INT_EVENT_TX, + INT_EVENT_RX, + INT_EVENT_NUM +}; + +typedef enum _ENUM_IE_UPD_METHOD_T { + IE_UPD_METHOD_UPDATE_RANDOM, + IE_UPD_METHOD_UPDATE_ALL, + IE_UPD_METHOD_DELETE_ALL, +} ENUM_IE_UPD_METHOD_T, *P_ENUM_IE_UPD_METHOD_T; + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in nic.c */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicAllocateAdapterMemory ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicReleaseAdapterMemory ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicDisableInterrupt ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicEnableInterrupt ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicProcessIST ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicProcessIST_impl ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4IntStatus + ); + +WLAN_STATUS +nicInitializeAdapter ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicMCRInit ( + IN P_ADAPTER_T prAdapter + ); + +BOOL +nicVerifyChipID ( + IN P_ADAPTER_T prAdapter + ); + + +#if CFG_SDIO_INTR_ENHANCE +VOID +nicSDIOInit ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicSDIOReadIntStatus ( + IN P_ADAPTER_T prAdapter, + OUT PUINT_32 pu4IntStatus + ); +#endif + +BOOLEAN +nicpmSetDriverOwn ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicpmSetFWOwn ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnableGlobalInt + ); + +BOOLEAN +nicpmSetAcpiPowerD0 ( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +nicpmSetAcpiPowerD3 ( + IN P_ADAPTER_T prAdapter + ); + +#if defined(_HIF_SPI) +void +nicRestoreSpiDefMode( + IN P_ADAPTER_T prAdapter + ); +#endif + +VOID +nicProcessSoftwareInterrupt( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicProcessAbnormalInterrupt ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicPutMailbox ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4MailboxNum, + IN UINT_32 u4Data); + +VOID +nicGetMailbox ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4MailboxNum, + OUT PUINT_32 pu4Data); + +VOID +nicSetSwIntr ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4SwIntrBitmap + ); + +P_CMD_INFO_T +nicGetPendingCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum + ); + +P_MSDU_INFO_T +nicGetPendingTxMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum + ); + +P_MSDU_INFO_T +nicGetPendingStaMMPDU( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx + ); + +VOID +nicFreePendingTxMsduInfoByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ); + +UINT_8 +nicIncreaseCmdSeqNum ( + IN P_ADAPTER_T prAdapter + ); + +UINT_8 +nicIncreaseTxSeqNum ( + IN P_ADAPTER_T prAdapter + ); + +/* Media State Change */ +WLAN_STATUS +nicMediaStateChange ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN P_EVENT_CONNECTION_STATUS prConnectionStatus + ); + +/* Utility function for channel number conversion */ +UINT_32 +nicChannelNum2Freq ( + IN UINT_32 u4ChannelNum + ); + +UINT_32 +nicFreq2ChannelNum ( + IN UINT_32 u4FreqInKHz + ); + +/* firmware command wrapper */ + /* NETWORK (WIFISYS) */ +WLAN_STATUS +nicActivateNetwork( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +WLAN_STATUS +nicDeactivateNetwork( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + + + /* BSS-INFO */ +WLAN_STATUS +nicUpdateBss( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + + /* BSS-INFO Indication (PM) */ +WLAN_STATUS +nicPmIndicateBssCreated( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +WLAN_STATUS +nicPmIndicateBssConnected( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +WLAN_STATUS +nicPmIndicateBssAbort( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + + /* Beacon Template Update */ +WLAN_STATUS +nicUpdateBeaconIETemplate ( + IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, + IN PUINT_8 aucIe, + IN UINT_16 u2IELen + ); + +WLAN_STATUS +nicQmUpdateWmmParms( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +WLAN_STATUS +nicSetAutoTxPower( + IN P_ADAPTER_T prAdapter, + IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam + ); + +/*----------------------------------------------------------------------------*/ +/* Calibration Control */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateTxPower( + IN P_ADAPTER_T prAdapter, + IN P_CMD_TX_PWR_T prTxPwrParam + ); + +WLAN_STATUS +nicUpdate5GOffset( + IN P_ADAPTER_T prAdapter, + IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset + ); + +WLAN_STATUS +nicUpdateDPD( + IN P_ADAPTER_T prAdapter, + IN P_CMD_PWR_PARAM_T prDpdCalResult + ); + + +/*----------------------------------------------------------------------------*/ +/* PHY configuration */ +/*----------------------------------------------------------------------------*/ +VOID +nicSetAvailablePhyTypeSet ( + IN P_ADAPTER_T prAdapter + ); + +/*----------------------------------------------------------------------------*/ +/* MGMT and System Service Control */ +/*----------------------------------------------------------------------------*/ +VOID +nicInitSystemService ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicResetSystemService ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicUninitSystemService ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicInitMGMT ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ); + +VOID +nicUninitMGMT ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicConfigPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + PARAM_POWER_MODE ePwrMode, + BOOLEAN fgEnCmdEvent + ); + +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +VOID +nicAddScanResult ( + IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_32 u4Privacy, + IN PARAM_RSSI rRssi, + IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, + IN P_PARAM_802_11_CONFIG_T prConfiguration, + IN ENUM_PARAM_OP_MODE_T eOpMode, + IN PARAM_RATES_EX rSupportedRates, + IN UINT_16 u2IELength, + IN PUINT_8 pucIEBuf + ); + +VOID +nicFreeScanResultIE ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Idx + ); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +/*----------------------------------------------------------------------------*/ +/* Workaround Control */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicEnableClockGating ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicDisableClockGating ( + IN P_ADAPTER_T prAdapter + ); +#endif + + +/*----------------------------------------------------------------------------*/ +/* Fixed Rate Hacking */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams ( + IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, + IN PUINT_8 pucSupMcs32, + IN PUINT_16 u2HtCapInfo + ); + +/*----------------------------------------------------------------------------*/ +/* Write registers */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicWriteMcr ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Address, + IN UINT_32 u4Value + ); + +/*----------------------------------------------------------------------------*/ +/* Update auto rate */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRlmArUpdateParms( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, + IN UINT_32 u4ArSysParam2, + IN UINT_32 u4ArSysParam3 + ); + +/*----------------------------------------------------------------------------*/ +/* Enable/Disable Roaming */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRoamingUpdateParams( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4EnableRoaming + ); + + +VOID +nicPrintFirmwareAssertInfo( + IN P_ADAPTER_T prAdapter + ); + +/*----------------------------------------------------------------------------*/ +/* Link Quality Updating */ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN P_EVENT_LINK_QUALITY prEventLinkQuality + ); + +VOID +nicUpdateRSSI( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN INT_8 cRssi, + IN INT_8 cLinkQuality + ); + +VOID +nicUpdateLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN UINT_16 u2LinkSpeed + ); + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS +nicUpdateRddTestMode( + IN P_ADAPTER_T prAdapter, + IN P_CMD_RDD_CH_T prRddChParam + ); +#endif + +#endif /* _NIC_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h new file mode 100755 index 000000000000..49ca2991abab --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h @@ -0,0 +1,529 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rx.h#1 $ +*/ + +/*! \file "nic_rx.h" + \brief The declaration of the nic rx functions + +*/ + + + +/* +** $Log: nic_rx.h $ + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Change prototype of API of adding P2P device to scan result. + * Additional IE buffer is saved. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 05 2010 yuche.tsai + * NULL + * Modify data structure for P2P Scan result. + * + * 08 03 2010 cp.wu + * NULL + * newly added P2P API should be declared in header file. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * 2) firmware image length is now retrieved via NdisFileOpen + * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * 4) nicRxWaitResponse() revised + * * 5) another set of TQ counter default value is added for fw-download state + * * 6) Wi-Fi load address is now retrieved from registry too + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * and result is retrieved by get ATInfo instead + * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:49:09 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 14:02:37 GMT MTK02468 +** Added ucStaRecIdx in SW_RFB_T and HALF_SEQ_NO_COUNT definition (to replace HALF_SEQ_NO_CNOUT) +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-27 11:07:54 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 18:18:09 GMT mtk02752 +** modify nicRxAddScanResult() +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-24 22:42:22 GMT mtk02752 +** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-24 19:57:06 GMT mtk02752 +** adopt P_HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 21:43:04 GMT mtk02752 +** correct ENUM_RX_PKT_DESTINATION_T definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 15:28:25 GMT mtk02752 +** add ucQueuedPacketNum for indicating how many packet are queued by RX reordering buffer/forwarding path +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 15:05:01 GMT mtk02752 +** add eTC for SW_RFB_T and structure RX_MAILBOX +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 21:16:57 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-13 16:59:30 GMT mtk02752 +** add handler for event packet +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-13 13:45:50 GMT mtk02752 +** add port param for nicRxEnhanceReadBuffer() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-11 10:12:31 GMT mtk02752 +** nicSDIOReadIntStatus() always read sizeof(ENHANCE_MODE_DATA_STRUCT_T) for int response, thus the number should be set to 0(:=16) instead of 10 +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-29 19:53:32 GMT mtk01084 +** modify structure naming +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-23 16:08:23 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:01 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-20 12:23:33 GMT mtk01461 +** Add u4MaxEventBufferLen parameter to nicRxWaitResponse() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-18 21:00:48 GMT mtk01426 +** Update SDIO_MAXIMUM_RX_STATUS value +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:36:15 GMT mtk01461 +** Remove unused define - SDIO_MAXIMUM_TX_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:17 GMT mtk01461 +** Add function for HIF_LOOPBACK_PRE_TEST +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:56:19 GMT mtk01426 +** Add to support CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:19:56 GMT mtk01426 +** Add nicRxWaitResponse function proto type +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:35 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_RX_H +#define _NIC_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0,10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + + +#if defined(_HIF_SDIO) && defined (WINDOWS_DDK) +/*! On XP, maximum Tx+Rx Statue <= 64-4(HISR)*/ + #define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#else + #define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_RX_STATISTIC_COUNTER_T { + RX_MPDU_TOTAL_COUNT = 0, + RX_SIZE_ERR_DROP_COUNT, + + RX_DATA_INDICATION_COUNT, + RX_DATA_RETURNED_COUNT, + RX_DATA_RETAINED_COUNT, + + RX_DROP_TOTAL_COUNT, + RX_TYPE_ERR_DROP_COUNT, + RX_CLASS_ERR_DROP_COUNT, + RX_DST_NULL_DROP_COUNT, + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + RX_CSUM_TCP_FAILED_COUNT, + RX_CSUM_UDP_FAILED_COUNT, + RX_CSUM_IP_FAILED_COUNT, + RX_CSUM_TCP_SUCCESS_COUNT, + RX_CSUM_UDP_SUCCESS_COUNT, + RX_CSUM_IP_SUCCESS_COUNT, + RX_CSUM_UNKNOWN_L4_PKT_COUNT, + RX_CSUM_UNKNOWN_L3_PKT_COUNT, + RX_IP_V6_PKT_CCOUNT, +#endif + RX_STATISTIC_COUNTER_NUM +} ENUM_RX_STATISTIC_COUNTER_T; + +typedef enum _ENUM_RX_PKT_DESTINATION_T { + RX_PKT_DESTINATION_HOST, /* to OS */ + RX_PKT_DESTINATION_FORWARD, /* to TX queue for forward, AP mode */ + RX_PKT_DESTINATION_HOST_WITH_FORWARD, /* to both TX and OS, AP mode broadcast packet */ + RX_PKT_DESTINATION_NULL, /* packet to be freed */ + RX_PKT_DESTINATION_NUM +} ENUM_RX_PKT_DESTINATION_T; + +struct _SW_RFB_T { + QUE_ENTRY_T rQueEntry; + PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ + PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4HifRxHdrFlag; + PVOID pvHeader; + UINT_16 u2PacketLen; + UINT_16 u2HeaderLen; + UINT_16 u2SSN; + UINT_8 ucTid; + UINT_8 ucWlanIdx; + UINT_8 ucPacketType; + UINT_8 ucStaRecIdx; + + ENUM_CSUM_RESULT_T aeCSUM[CSUM_TYPE_NUM]; + ENUM_RX_PKT_DESTINATION_T eDst; + ENUM_TRAFFIC_CLASS_INDEX_T eTC; /* only valid when eDst == FORWARD */ +}; + +/*! RX configuration type structure */ +typedef struct _RX_CTRL_T { + UINT_32 u4RxCachedSize; + PUINT_8 pucRxCached; + QUE_T rFreeSwRfbList; + QUE_T rReceivedRfbList; + QUE_T rIndicatedRfbList; + +#if CFG_SDIO_RX_AGG + PUINT_8 pucRxCoalescingBufPtr; +#endif + + PVOID apvIndPacket[CFG_RX_MAX_PKT_NUM]; + PVOID apvRetainedPacket[CFG_RX_MAX_PKT_NUM]; + + UINT_8 ucNumIndPacket; + UINT_8 ucNumRetainedPacket; + UINT_64 au8Statistics[RX_STATISTIC_COUNTER_NUM]; /*!< RX Counters */ + +#if CFG_HIF_STATISTICS + UINT_32 u4TotalRxAccessNum; + UINT_32 u4TotalRxPacketNum; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + UINT_32 u4QueuedCnt; + UINT_32 u4DequeuedCnt; +#endif + +#if CFG_RX_PKTS_DUMP + UINT_32 u4RxPktsDumpTypeMask; +#endif + +} RX_CTRL_T, *P_RX_CTRL_T; + +typedef struct _RX_MAILBOX_T { + UINT_32 u4RxMailbox[2]; /* for Device-to-Host Mailbox */ +} RX_MAILBOX_T, *P_RX_MAILBOX_T; + +typedef WLAN_STATUS (*PROCESS_RX_MGT_FUNCTION)(P_ADAPTER_T, P_SW_RFB_T); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RX_INC_CNT(prRxCtrl, eCounter) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]++;} + +#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter] += (UINT_64)u8Amount;} + +#define RX_GET_CNT(prRxCtrl, eCounter) \ + (((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]) + +#define RX_RESET_ALL_CNTS(prRxCtrl) \ + {kalMemZero(&prRxCtrl->au8Statistics[0], sizeof(prRxCtrl->au8Statistics));} + +#define RX_STATUS_TEST_MORE_FLAG(flag) \ + ((BOOL)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +nicRxInitialize ( + IN P_ADAPTER_T prAdapter + ); + +#if defined(MT5931) +VOID +nicRxPostInitialize ( + IN P_ADAPTER_T prAdapter + ); +#endif + +VOID +nicRxUninitialize ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicRxProcessRFBs ( + IN P_ADAPTER_T prAdapter + ); + +#if !CFG_SDIO_INTR_ENHANCE +VOID +nicRxReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicRxReadBuffer ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ); + +#else +VOID +nicRxSDIOReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicRxEnhanceReadBuffer ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, + IN UINT_16 u2RxLength, + IN OUT P_SW_RFB_T prSwRfb + ); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + +#if CFG_SDIO_RX_AGG +VOID +nicRxSDIOAggReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ); +#endif + +WLAN_STATUS +nicRxSetupRFB ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prRfb + ); + +VOID +nicRxReturnRFB ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prRfb + ); + +VOID +nicProcessRxInterrupt ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicRxProcessPktWithoutReorder ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +nicRxProcessForwardPkt ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +VOID +nicRxProcessGOBroadcastPkt ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + + +VOID +nicRxFillRFB ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ); + +VOID +nicRxProcessDataPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ); + +VOID +nicRxProcessEventPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ); + +VOID +nicRxProcessMgmtPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID +nicRxFillChksumStatus( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb, + IN UINT_32 u4TcpUdpIpCksStatus + ); + +VOID +nicRxUpdateCSUMStatistics ( + IN P_ADAPTER_T prAdapter, + IN const ENUM_CSUM_RESULT_T aeCSUM[] + ); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +VOID +nicRxQueryStatus ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + OUT PUINT_32 pu4Count + ); + +VOID +nicRxClearStatistics ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicRxQueryStatistics ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + OUT PUINT_32 pu4Count + ); + +WLAN_STATUS +nicRxWaitResponse ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, + OUT PUINT_8 pucRspBuffer, + IN UINT_32 u4MaxRespBufferLen, + OUT PUINT_32 pu4Length + ); + +VOID +nicRxEnablePromiscuousMode ( + IN P_ADAPTER_T prAdapter + ); + + +VOID +nicRxDisablePromiscuousMode ( + IN P_ADAPTER_T prAdapter + ); + + +WLAN_STATUS +nicRxFlush ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicRxProcessActionFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +#endif /* _NIC_RX_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h new file mode 100755 index 000000000000..4837da4877ca --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h @@ -0,0 +1,646 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_tx.h#1 $ +*/ + +/*! \file nic_tx.h + \brief Functions that provide TX operation in NIC's point of view. + + This file provides TX functions which are responsible for both Hardware and + Software Resource Management and keep their Synchronization. + +*/ + + + +/* +** $Log: nic_tx.h $ + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add log counter for tx + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add TX_DONE status detail information. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 02 16 2011 cp.wu + * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking availble count and modify behavior + * 1. add new API: nicTxGetFreeCmdCount() + * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 12 15 2010 yuche.tsai + * NULL + * Update SLT Descriptor number configure in driver. + * + * 11 16 2010 yarco.yang + * [WCXRP00000177] [MT5931 F/W] Performance tuning for 1st connection + * Update TX buffer count + * + * 11 03 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) use 8 buffers for MT5931 which is equipped with less memory + * 2) modify MT5931 debug level to TRACE when download is successful + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 07 26 2010 cp.wu + * + * change TC4 initial value from 2 to 4. + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add MGMT Packet type for HIF_TX_HEADER + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate + * 2) add packet type for indicating management frames + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add TX_PACKET_MGMT to indicate the frame is coming from management modules + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 02 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Redistributed the initial TC resources for normal operation + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * 4) nicRxWaitResponse() revised + * * * 5) another set of TQ counter default value is added for fw-download state + * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * 4. correct some HAL implementation + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * and result is retrieved by get ATInfo instead + * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:53:28 GMT mtk02752 +** remove unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-27 11:08:00 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-24 19:56:49 GMT mtk02752 +** remove redundant eTC +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 22:01:08 GMT mtk02468 +** Added MSDU_INFO fields for composing HIF TX header +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:51 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:35:05 GMT mtk02752 +** + nicTxMsduInfoList() for sending MsduInfoList +** + NIC_TX_BUFF_COUNT_TC[0~5] +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-17 11:07:00 GMT mtk02752 +** add nicTxAdjustTcq() API +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 22:28:30 GMT mtk02752 +** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 21:44:50 GMT mtk02752 +** + nicTxReturnMsduInfo() +** + nicTxFillMsduInfo() +** + rFreeMsduInfoList field in TX_CTRL +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-16 18:00:43 GMT mtk02752 +** use P_PACKET_INFO_T for prPacket to avoid inventing another new structure for packet +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-16 15:28:49 GMT mtk02752 +** add ucQueuedPacketNum for indicating how many packets are queued by per STA/AC queue +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-16 10:52:01 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-14 23:39:24 GMT mtk02752 +** interface structure redefine +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-13 21:17:03 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-29 19:53:10 GMT mtk01084 +** remove strange code by Frog +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:04 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-02 13:53:03 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:36:50 GMT mtk01461 +** Add declaration of nicTxReleaseResource() +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:58:39 GMT mtk01461 +** Move CMD_INFO_T related define and function to cmd_buf.h +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:53 GMT mtk01461 +** Add function for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:33:27 GMT mtk01461 +** Define constants for TX PATH and add nicTxPollingResource +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:32 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:38 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_TX_H +#define _NIC_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 50 + +/* Maximum buffer count for individual HIF TCQ */ + +#if defined(MT6620) +#if CFG_SLT_SUPPORT + /* 20101215 mtk01725 Redistributed the initial TC resources for SLT operation */ + #define NIC_TX_BUFF_COUNT_TC0 0 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC1 16 // First connection: 32 + #define NIC_TX_BUFF_COUNT_TC2 0 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC3 0 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC4 4 // First connection: 2 + #define NIC_TX_BUFF_COUNT_TC5 0 // First connection: 0 +#else + /* 20100302 mtk02468 Redistributed the initial TC resources for normal operation */ + #define NIC_TX_BUFF_COUNT_TC0 6 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC1 8 // First connection: 32 + #define NIC_TX_BUFF_COUNT_TC2 8 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC3 8 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC4 4 // First connection: 2 + #define NIC_TX_BUFF_COUNT_TC5 2 // First connection: 0 +#endif +#elif defined(MT5931) + #define NIC_TX_BUFF_COUNT_TC0 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC1 14 // First connection: 32 + #define NIC_TX_BUFF_COUNT_TC2 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC3 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC4 4 // First connection: 2 + #define NIC_TX_BUFF_COUNT_TC5 1 // First connection: 0 +#elif defined(MT6628) + #define NIC_TX_BUFF_COUNT_TC0 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC1 20 // First connection: 32 + #define NIC_TX_BUFF_COUNT_TC2 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC3 1 // First connection: 0 + #define NIC_TX_BUFF_COUNT_TC4 4 // First connection: 2 + #define NIC_TX_BUFF_COUNT_TC5 1 // First connection: 0 + +#endif + +#define NIC_TX_BUFF_SUM (NIC_TX_BUFF_COUNT_TC0 + \ + NIC_TX_BUFF_COUNT_TC1 + \ + NIC_TX_BUFF_COUNT_TC2 + \ + NIC_TX_BUFF_COUNT_TC3 + \ + NIC_TX_BUFF_COUNT_TC4 + \ + NIC_TX_BUFF_COUNT_TC5) +#if CFG_ENABLE_FW_DOWNLOAD + + #define NIC_TX_INIT_BUFF_COUNT_TC0 8 + #define NIC_TX_INIT_BUFF_COUNT_TC1 0 + #define NIC_TX_INIT_BUFF_COUNT_TC2 0 + #define NIC_TX_INIT_BUFF_COUNT_TC3 0 + #define NIC_TX_INIT_BUFF_COUNT_TC4 0 + #define NIC_TX_INIT_BUFF_COUNT_TC5 0 + + #define NIC_TX_INIT_BUFF_SUM (NIC_TX_INIT_BUFF_COUNT_TC0 + \ + NIC_TX_INIT_BUFF_COUNT_TC1 + \ + NIC_TX_INIT_BUFF_COUNT_TC2 + \ + NIC_TX_INIT_BUFF_COUNT_TC3 + \ + NIC_TX_INIT_BUFF_COUNT_TC4 + \ + NIC_TX_INIT_BUFF_COUNT_TC5) + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +//3 /* Session for TX QUEUES */ +/* The definition in this ENUM is used to categorize packet's Traffic Class according + * to the their TID(User Priority). + * In order to achieve QoS goal, a particular TC should not block the process of + * another packet with different TC. + * In current design we will have 5 categories(TCs) of SW resource. + */ +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + TC0_INDEX = 0, /* HIF TX0: AC0 packets */ + TC1_INDEX, /* HIF TX0: AC1 packets & non-QoS packets */ + TC2_INDEX, /* HIF TX0: AC2 packets */ + TC3_INDEX, /* HIF TX0: AC3 packets */ + TC4_INDEX, /* HIF TX1: Command packets or 802.1x packets */ + TC5_INDEX, /* HIF TX0: BMCAST packets */ + TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_TRAFFIC_CLASS_INDEX_T; + +typedef enum _ENUM_TX_STATISTIC_COUNTER_T { + TX_MPDU_TOTAL_COUNT = 0, + TX_INACTIVE_BSS_DROP, + TX_INACTIVE_STA_DROP, + TX_FORWARD_OVERFLOW_DROP, + TX_AP_BORADCAST_DROP, + TX_STATISTIC_COUNTER_NUM +} ENUM_TX_STATISTIC_COUNTER_T; + + +typedef struct _TX_TCQ_STATUS_T { + UINT_8 aucFreeBufferCount[TC_NUM]; + UINT_8 aucMaxNumOfBuffer[TC_NUM]; +} TX_TCQ_STATUS_T, *P_TX_TCQ_STATUS_T; + +typedef struct _TX_TCQ_ADJUST_T { + INT_8 acVariation[TC_NUM]; +} TX_TCQ_ADJUST_T, *P_TX_TCQ_ADJUST_T; + +typedef struct _TX_CTRL_T { + UINT_32 u4TxCachedSize; + PUINT_8 pucTxCached; + +/* Elements below is classified according to TC (Traffic Class) value. */ + + TX_TCQ_STATUS_T rTc; + + PUINT_8 pucTxCoalescingBufPtr; + + QUE_T rFreeMsduInfoList; + + /* Management Frame Tracking */ + /* number of management frames to be sent */ + INT_32 i4TxMgmtPendingNum; + + /* to tracking management frames need TX done callback */ + QUE_T rTxMgmtTxingQueue; + +#if CFG_HIF_STATISTICS + UINT_32 u4TotalTxAccessNum; + UINT_32 u4TotalTxPacketNum; +#endif + UINT_32 au4Statistics[TX_STATISTIC_COUNTER_NUM]; + + /* Number to track forwarding frames */ + INT_32 i4PendingFwdFrameCount; + +} TX_CTRL_T, *P_TX_CTRL_T; + +typedef enum _ENUM_TX_PACKET_SRC_T { + TX_PACKET_OS, + TX_PACKET_OS_OID, + TX_PACKET_FORWARDING, + TX_PACKET_MGMT, + TX_PACKET_NUM +} ENUM_TX_PACKET_SRC_T; + +typedef enum _ENUM_HIF_TX_PACKET_TYPE_T { + HIF_TX_PACKET_TYPE_DATA = 0, + HIF_TX_PACKET_TYPE_COMMAND, + HIF_TX_PACKET_TYPE_HIF_LB, + HIF_TX_PACKET_TYPE_MGMT +} ENUM_HIF_TX_PACKET_TYPE_T, *P_ENUM_HIF_TX_PACKET_TYPE_T; + +typedef enum _ENUM_TX_RESULT_CODE_T { + TX_RESULT_SUCCESS = 0, + TX_RESULT_LIFE_TIMEOUT, + TX_RESULT_RTS_ERROR, + TX_RESULT_MPDU_ERROR, + TX_RESULT_AGING_TIMEOUT, + TX_RESULT_FLUSHED, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_NUM +} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; + +/* TX Call Back Function */ +typedef WLAN_STATUS (*PFN_TX_DONE_HANDLER) ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +/* TX transactions could be divided into 4 kinds: + * + * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames + * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + * + * 2) MMPDU + * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body + * + * 3) Command Packets + * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet + * + * 4) Normal data frame + * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + */ + + +/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode +* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) +*/ + +struct _MSDU_INFO_T { + QUE_ENTRY_T rQueEntry; + P_NATIVE_PACKET prPacket; + + ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ + UINT_8 ucUserPriority; + + /* For composing HIF TX header */ + UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + UINT_8 ucPacketType; /* 0: Data, 1: Command, 2: HIF Loopback 3: Management Frame */ + UINT_8 ucStaRecIndex; + UINT_8 ucNetworkType; /* See ENUM_NETWORK_TYPE_T */ + UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ + BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ + UINT_16 u2PalLLH; /* PAL Logical Link Header (for BOW network) */ + UINT_16 u2AclSN; /* ACL Sequence Number (for BOW network) */ + UINT_8 ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ + UINT_8 ucPsSessionID; /* PS Session ID specified by the FW for the STA */ + BOOLEAN fgIsBurstEnd; /* TRUE means this is the last packet of the burst for (STA, TID) */ + BOOLEAN fgIsBIP; /* Management Frame Protection */ + BOOLEAN fgIsBasicRate; /* Force Basic Rate Transmission */ + + /* flattened from PACKET_INFO_T */ + UINT_8 ucMacHeaderLength; + UINT_8 ucLlcLength; /* w/o EtherType */ + UINT_16 u2FrameLength; + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ + + /* for TX done tracking */ + UINT_8 ucTxSeqNum; + PFN_TX_DONE_HANDLER pfTxDoneHandler; +}; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++;} + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount;} + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics));} + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +nicTxInitialize ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicTxAcquireResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ); + +WLAN_STATUS +nicTxPollingResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ); + +BOOLEAN +nicTxReleaseResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8* aucTxRlsCnt + ); + +WLAN_STATUS +nicTxResetResource ( + IN P_ADAPTER_T prAdapter + ); + +UINT_8 +nicTxGetResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ); + +WLAN_STATUS +nicTxMsduInfoList ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ); + +WLAN_STATUS +nicTxMsduQueue ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucPortIdx, + P_QUE_T prQue + ); + +WLAN_STATUS +nicTxCmd ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN UINT_8 ucTC + ); + +VOID +nicTxRelease ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicProcessTxInterrupt ( + IN P_ADAPTER_T prAdapter + ); + +VOID +nicTxFreeMsduInfoPacket ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ); + +VOID +nicTxReturnMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ); + +BOOLEAN +nicTxFillMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prNdisPacket + ); + +WLAN_STATUS +nicTxAdjustTcq ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +nicTxFlush ( + IN P_ADAPTER_T prAdapter + ); + +#if CFG_ENABLE_FW_DOWNLOAD +WLAN_STATUS +nicTxInitCmd ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN UINT_8 ucTC + ); + +WLAN_STATUS +nicTxInitResetResource ( + IN P_ADAPTER_T prAdapter + ); +#endif + +WLAN_STATUS +nicTxEnqueueMsdu ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +UINT_32 +nicTxGetFreeCmdCount ( + IN P_ADAPTER_T prAdapter + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_TX_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h new file mode 100755 index 000000000000..30bae79019e1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h @@ -0,0 +1,195 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 $ +*/ + + + +/* +** $Log: p2p.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * p2p interface revised to be sync. with HAL + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 18 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add parameter to control: + * 1) auto group owner + * 2) P2P-PS parameter (CTWindow, NoA descriptors) + * + * 05 18 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * correct WPS Device Password ID definition. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * +*/ + +#ifndef _P2P_H +#define _P2P_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +// refer to 'Config Methods' in WPS +#define WPS_CONFIG_USBA 0x0001 +#define WPS_CONFIG_ETHERNET 0x0002 +#define WPS_CONFIG_LABEL 0x0004 +#define WPS_CONFIG_DISPLAY 0x0008 +#define WPS_CONFIG_EXT_NFC 0x0010 +#define WPS_CONFIG_INT_NFC 0x0020 +#define WPS_CONFIG_NFC 0x0040 +#define WPS_CONFIG_PBC 0x0080 +#define WPS_CONFIG_KEYPAD 0x0100 + +// refer to 'Device Password ID' in WPS +#define WPS_DEV_PASSWORD_ID_PIN 0x0000 +#define WPS_DEV_PASSWORD_ID_USER 0x0001 +#define WPS_DEV_PASSWORD_ID_MACHINE 0x0002 +#define WPS_DEV_PASSWORD_ID_REKEY 0x0003 +#define WPS_DEV_PASSWORD_ID_PUSHBUTTON 0x0004 +#define WPS_DEV_PASSWORD_ID_REGISTRAR 0x0005 + + +#define P2P_DEVICE_TYPE_NUM 2 +#define P2P_DEVICE_NAME_LENGTH 32 +#define P2P_NETWORK_NUM 8 +#define P2P_MEMBER_NUM 8 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct _P2P_INFO_T { + UINT_32 u4DeviceNum; + EVENT_P2P_DEV_DISCOVER_RESULT_T arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 pucCurrIePtr; + UINT_8 aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; /* A common pool for IE of all scan results. */ +}; + +typedef enum { + ENUM_P2P_PEER_GROUP, + ENUM_P2P_PEER_DEVICE, + ENUM_P2P_PEER_NUM +} ENUM_P2P_PEER_TYPE, *P_ENUM_P2P_PEER_TYPE; + +typedef struct _P2P_DEVICE_INFO { + UINT_8 aucDevAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 aucIfAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDevCapabilityBitmap; + INT_32 i4ConfigMethod; + UINT_8 aucPrimaryDeviceType[8]; + UINT_8 aucSecondaryDeviceType[8]; + UINT_8 aucDeviceName[P2P_DEVICE_NAME_LENGTH]; +} P2P_DEVICE_INFO, *P_P2P_DEVICE_INFO; + +typedef struct _P2P_GROUP_INFO { + PARAM_SSID_T rGroupID; + P2P_DEVICE_INFO rGroupOwnerInfo; + UINT_8 ucMemberNum; + P2P_DEVICE_INFO arMemberInfo[P2P_MEMBER_NUM]; +} P2P_GROUP_INFO, *P_P2P_GROUP_INFO; + +typedef struct _P2P_NETWORK_INFO { + ENUM_P2P_PEER_TYPE eNodeType; + + union { + P2P_GROUP_INFO rGroupInfo; + P2P_DEVICE_INFO rDeviceInfo; + } node; + +} P2P_NETWORK_INFO, *P_P2P_NETWORK_INFO; + +typedef struct _P2P_NETWORK_LIST { + UINT_8 ucNetworkNum; + P2P_NETWORK_INFO rP2PNetworkInfo[P2P_NETWORK_NUM]; +} P2P_NETWORK_LIST, *P_P2P_NETWORK_LIST; + +typedef struct _P2P_DISCONNECT_INFO { + UINT_8 ucRole; + UINT_8 ucRsv[3]; +} P2P_DISCONNECT_INFO, *P_P2P_DISCONNECT_INFO; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h new file mode 100755 index 000000000000..c59c60678d44 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h @@ -0,0 +1,93 @@ +/* +** $Id: +*/ + +/*! \file "p2p_cmd_buf.h" + \brief In this file we define the structure for Command Packet. + + In this file we define the structure for Command Packet and the control unit + of MGMT Memory Pool. +*/ + + + +/* +** $Log: p2p_cmd_buf.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks +*/ + +#ifndef _P2P_CMD_BUF_H +#define _P2P_CMD_BUF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, + OUT PVOID pvSetQueryBuffer, + IN UINT_32 u4SetQueryBufferLen + ); + + + + +#endif /* _P2P_CMD_BUF_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h new file mode 100755 index 000000000000..9c022b0193b8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h @@ -0,0 +1,223 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_mac.h#2 $ +*/ + +/*! \file "p2p_mac.h" + \brief Brief description. + + Detail description. +*/ + + + + + +#ifndef _P2P_MAC_H +#define _P2P_MAC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define ACTION_PUBLIC_WIFI_DIRECT 9 +#define ACTION_GAS_INITIAL_REQUEST 10 +#define ACTION_GAS_INITIAL_RESPONSE 11 +#define ACTION_GAS_COMEBACK_REQUEST 12 +#define ACTION_GAS_COMEBACK_RESPONSE 13 + + +/* P2P 4.2.8.1 - P2P Public Action Frame Type. */ +#define P2P_PUBLIC_ACTION_GO_NEGO_REQ 0 +#define P2P_PUBLIC_ACTION_GO_NEGO_RSP 1 +#define P2P_PUBLIC_ACTION_GO_NEGO_CFM 2 +#define P2P_PUBLIC_ACTION_INVITATION_REQ 3 +#define P2P_PUBLIC_ACTION_INVITATION_RSP 4 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ 5 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP 6 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ 7 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP 8 + +/* P2P 4.2.9.1 - P2P Action Frame Type */ +#define P2P_ACTION_NOTICE_OF_ABSENCE 0 +#define P2P_ACTION_P2P_PRESENCE_REQ 1 +#define P2P_ACTION_P2P_PRESENCE_RSP 2 +#define P2P_ACTION_GO_DISCOVER_REQ 3 + +#define P2P_PUBLIC_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+8) +#define P2P_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+7) + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/* P2P 4.2.8.2 P2P Public Action Frame Format */ +typedef struct _P2P_PUBLIC_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ + UINT_8 ucOuiType; /* 0x09 */ + UINT_8 ucOuiSubtype; /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, Device Discoverability Req/Rsp */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* P2P IE, WSC IE. */ +} __KAL_ATTRIB_PACKED__ P2P_PUBLIC_ACTION_FRAME_T, *P_P2P_PUBLIC_ACTION_FRAME_T; + + +/* P2P 4.2.9.1 - General Action Frame Format. */ +typedef struct _P2P_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Action Frame Body */ + UINT_8 ucCategory; // 0x7F + UINT_8 aucOui[3]; // 0x50, 0x6F, 0x9A + UINT_8 ucOuiType; // 0x09 + UINT_8 ucOuiSubtype; // + UINT_8 ucDialogToken; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ P2P_ACTION_FRAME_T, *P_P2P_ACTION_FRAME_T; + +/* P2P C.1 GAS Public Action Initial Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T; + +/* P2P C.2 GAS Public Action Initial Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Initial Response. */ + UINT_16 u2ComebackDelay; /* Initial Response. */ /* In unit of TU. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T; + + +/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T; + +/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Comeback Response. */ + UINT_8 ucFragmentID; /*Comeback Response. */ + UINT_16 u2ComebackDelay; /* Comeback Response. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T; + + + + +typedef struct _P2P_SD_VENDER_SPECIFIC_CONTENT_T { + /* Service Discovery Vendor-specific Content. */ + UINT_8 ucOuiSubtype; // 0x09 + UINT_16 u2ServiceUpdateIndicator; + UINT_8 aucServiceTLV[1]; +} __KAL_ATTRIB_PACKED__ P2P_SD_VENDER_SPECIFIC_CONTENT_T, *P_P2P_SD_VENDER_SPECIFIC_CONTENT_T; + + +typedef struct _P2P_SERVICE_REQUEST_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 aucQueryData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_REQUEST_TLV_T, *P_P2P_SERVICE_REQUEST_TLV_T; + + + +typedef struct _P2P_SERVICE_RESPONSE_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 ucStatusCode; + UINT_8 aucResponseData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_RESPONSE_TLV_T, *P_P2P_SERVICE_RESPONSE_TLV_T; + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h new file mode 100755 index 000000000000..3f1363f77d1a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h @@ -0,0 +1,74 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic.h#1 $ +*/ + +/*! \file "p2p_nic.h" + \brief The declaration of nic functions + + Detail description. +*/ + + + + + +#ifndef _P2P_NIC_H +#define _P2P_NIC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +VOID +nicP2pMediaStateChange( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN P_EVENT_CONNECTION_STATUS prConnectionStatus + ); + +VOID +nicRxAddP2pDevice( + IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, + IN PUINT_8 pucRxIEBuf, + IN UINT_16 u2RxIELength + ); + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h new file mode 100755 index 000000000000..fb056fff3598 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,73 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic_cmd_event.h#1 $ +*/ + +/*! \file p2p_nic_cmd_event.h + \brief +*/ + + + +#ifndef _P2P_NIC_CMD_EVENT_H +#define _P2P_NIC_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { +// UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[2]; + UINT_16 u2NameLength; + UINT_8 aucName[32]; + PUINT_8 pucIeBuf; + UINT_16 u2IELength; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + // TODO: Service Information or PasswordID valid? +} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; + +#endif \ No newline at end of file diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h new file mode 100755 index 000000000000..fd31ecd66f73 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h @@ -0,0 +1,1150 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#1 $ +*/ + +/*! \file "que_mgt.h" + \brief TX/RX queues management header file + + The main tasks of queue management include TC-based HIF TX flow control, + adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save + forwarding control, RX packet reordering, and RX BA agreement management. +*/ + + + +/* +** $Log: que_mgt.h $ + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 07 26 2011 eddie.chen + * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter + * API for query the RX reorder queued packets counter. + * + * 06 14 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Change the parameter for WMM pass. + * + * 05 31 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Fix the QM quota in MT5931. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 28 2011 eddie.chen + * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW + * Fix wmm parameters in beacon for BOW. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Chnage GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * 1) Check Bss if support QoS before adding WMMIE + * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 07 22 2010 george.huang + * + * Update fgIsQoS information in BSS INFO by CMD + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 yarco.yang + * + * [WPD00003849] + * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled adaptive TC resource control + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 19 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * By default enabling dynamic STA_REC activation and decactivation + * + * 03 17 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) + * + * 03 11 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed buffer leak when processing BAR frames + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled multi-STA TX path with fairness + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled dynamically activating and deactivating STA_RECs + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for dynamic activating and deactivating STA_RECs. + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:04:53 GMT MTK02468 +** Added RX buffer reordering function prototypes +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-02 22:08:44 GMT MTK02468 +** Added macro QM_INIT_STA_REC for initialize a STA_REC +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 21:58:43 GMT mtk02468 +** Initial version +** +*/ + +#ifndef _QUE_MGT_H +#define _QUE_MGT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Queue Manager Features */ +#define QM_BURST_END_INFO_ENABLED 1 /* 1: Indicate the last TX packet to the FW for each burst */ +#define QM_FORWARDING_FAIRNESS 1 /* 1: To fairly share TX resource among active STAs */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 /* 1: To adaptively adjust resource for each TC */ +#define QM_PRINT_TC_RESOURCE_CTRL 0 /* 1: To print TC resource adjustment results */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 /* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 /* 1: Indicate the packets falling behind to OS before the frame with SSN is received */ +/* Parameters */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 60 /* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 3 /* s: Adjust the TC resource every s updates of queue lengths */ +#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 /* Factor for Que Len averaging */ + +#define QM_MIN_RESERVED_TC0_RESOURCE 1 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 1 +#define QM_MIN_RESERVED_TC3_RESOURCE 1 +#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC5_RESOURCE 1 + +#if defined(MT6620) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 9 +#define QM_GUARANTEED_TC3_RESOURCE 11 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#elif defined(MT5931) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 4 +#define QM_GUARANTEED_TC3_RESOURCE 4 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 2 + +#elif defined(MT6628) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 6 +#define QM_GUARANTEED_TC3_RESOURCE 6 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + + +#else +#error +#endif + + + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_TOTAL_TC_RESOURCE (\ + NIC_TX_BUFF_COUNT_TC0 + NIC_TX_BUFF_COUNT_TC1 +\ + NIC_TX_BUFF_COUNT_TC2 + NIC_TX_BUFF_COUNT_TC3 +\ + NIC_TX_BUFF_COUNT_TC5) +#define QM_AVERAGE_TC_RESOURCE 6 + +/* Note: QM_INITIAL_RESIDUAL_TC_RESOURCE shall not be less than 0 */ +#define QM_INITIAL_RESIDUAL_TC_RESOURCE (QM_TOTAL_TC_RESOURCE - \ + (QM_GUARANTEED_TC0_RESOURCE +\ + QM_GUARANTEED_TC1_RESOURCE +\ + QM_GUARANTEED_TC2_RESOURCE +\ + QM_GUARANTEED_TC3_RESOURCE +\ + QM_GUARANTEED_TC5_RESOURCE \ + )) + +/* Hard-coded network type for Phase 3: NETWORK_TYPE_AIS/P2P/BOW */ +#define QM_OPERATING_NETWORK_TYPE NETWORK_TYPE_AIS + +#define QM_TEST_MODE 0 +#define QM_TEST_TRIGGER_TX_COUNT 50 +#define QM_TEST_STA_REC_DETERMINATION 0 +#define QM_TEST_STA_REC_DEACTIVATION 0 +#define QM_TEST_FAIR_FORWARDING 0 + +#define QM_DEBUG_COUNTER 0 + +/* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 5 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* These two constants are also used for FW to verify the STA_REC index */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE + +/* TX Queue Index */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 +#define TX_QUEUE_INDEX_AC0 0 +#define TX_QUEUE_INDEX_AC1 1 +#define TX_QUEUE_INDEX_AC2 2 +#define TX_QUEUE_INDEX_AC3 3 +#define TX_QUEUE_INDEX_802_1X 4 +#define TX_QUEUE_INDEX_NON_QOS 1 + + +//1 WMM-related +/* WMM FLAGS */ +#define WMM_FLAG_SUPPORT_WMM BIT(0) +#define WMM_FLAG_SUPPORT_WMMSA BIT(1) +#define WMM_FLAG_AC_PARAM_PRESENT BIT(2) +#define WMM_FLAG_SUPPORT_UAPSD BIT(3) + +/* WMM Admission Control Mandatory FLAGS */ +#define ACM_FLAG_ADM_NOT_REQUIRED 0 +#define ACM_FLAG_ADM_GRANTED BIT(0) +#define ACM_FLAG_ADM_REQUIRED BIT(1) + +/* WMM Power Saving FLAGS */ +#define AC_FLAG_TRIGGER_ENABLED BIT(1) +#define AC_FLAG_DELIVERY_ENABLED BIT(2) + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* WMM-2.2.2 WMM Parameter Element */ +#define ELEM_MAX_LEN_WMM_PARAM 24 + +/* WMM-2.2.1 WMM QoS Info field */ +#define WMM_QOS_INFO_PARAM_SET_CNT BITS(0,3) /* Sent by AP */ +#define WMM_QOS_INFO_UAPSD BIT(7) + +#define WMM_QOS_INFO_VO_UAPSD BIT(0) /* Sent by non-AP STA */ +#define WMM_QOS_INFO_VI_UAPSD BIT(1) +#define WMM_QOS_INFO_BK_UAPSD BIT(2) +#define WMM_QOS_INFO_BE_UAPSD BIT(3) +#define WMM_QOS_INFO_MAX_SP_LEN_MASK BITS(5,6) +#define WMM_QOS_INFO_MAX_SP_ALL 0 +#define WMM_QOS_INFO_MAX_SP_2 BIT(5) +#define WMM_QOS_INFO_MAX_SP_4 BIT(6) +#define WMM_QOS_INFO_MAX_SP_6 BITS(5,6) + +/* -- definitions for Max SP length field */ +#define WMM_MAX_SP_LENGTH_ALL 0 +#define WMM_MAX_SP_LENGTH_2 2 +#define WMM_MAX_SP_LENGTH_4 4 +#define WMM_MAX_SP_LENGTH_6 6 + + +/* WMM-2.2.2 WMM ACI/AIFSN field */ +/* -- subfields in the ACI/AIFSN field */ +#define WMM_ACIAIFSN_AIFSN BITS(0,3) +#define WMM_ACIAIFSN_ACM BIT(4) +#define WMM_ACIAIFSN_ACI BITS(5,6) +#define WMM_ACIAIFSN_ACI_OFFSET 5 + +/* -- definitions for ACI field */ +#define WMM_ACI_AC_BE 0 +#define WMM_ACI_AC_BK BIT(5) +#define WMM_ACI_AC_VI BIT(6) +#define WMM_ACI_AC_VO BITS(5,6) + +#define WMM_ACI(_AC) (_AC << WMM_ACIAIFSN_ACI_OFFSET) + +/* -- definitions for ECWmin/ECWmax field */ +#define WMM_ECW_WMIN_MASK BITS(0,3) +#define WMM_ECW_WMAX_MASK BITS(4,7) +#define WMM_ECW_WMAX_OFFSET 4 + +#define TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME 0 /* Unit: 64 us */ + +#define QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum { + QM_DBG_CNT_00=0, + QM_DBG_CNT_01, + QM_DBG_CNT_02, + QM_DBG_CNT_03, + QM_DBG_CNT_04, + QM_DBG_CNT_05, + QM_DBG_CNT_06, + QM_DBG_CNT_07, + QM_DBG_CNT_08, + QM_DBG_CNT_09, + QM_DBG_CNT_10, + QM_DBG_CNT_11, + QM_DBG_CNT_12, + QM_DBG_CNT_13, + QM_DBG_CNT_14, + QM_DBG_CNT_15, + QM_DBG_CNT_16, + QM_DBG_CNT_17, + QM_DBG_CNT_18, + QM_DBG_CNT_19, + QM_DBG_CNT_20, + QM_DBG_CNT_21, + QM_DBG_CNT_22, + QM_DBG_CNT_23, + QM_DBG_CNT_24, + QM_DBG_CNT_25, + QM_DBG_CNT_26, + QM_DBG_CNT_27, + QM_DBG_CNT_28, + QM_DBG_CNT_29, + QM_DBG_CNT_30, + QM_DBG_CNT_31, + QM_DBG_CNT_NUM +}; + + + + +/* Used for MAC TX */ +typedef enum _ENUM_MAC_TX_QUEUE_INDEX_T { + MAC_TX_QUEUE_AC0_INDEX = 0, + MAC_TX_QUEUE_AC1_INDEX, + MAC_TX_QUEUE_AC2_INDEX, + MAC_TX_QUEUE_AC3_INDEX, + MAC_TX_QUEUE_AC4_INDEX, + MAC_TX_QUEUE_AC5_INDEX, + MAC_TX_QUEUE_AC6_INDEX, + MAC_TX_QUEUE_BCN_INDEX, + MAC_TX_QUEUE_BMC_INDEX, + MAC_TX_QUEUE_NUM +} ENUM_MAC_TX_QUEUE_INDEX_T; + +typedef struct _RX_BA_ENTRY_T { + BOOLEAN fgIsValid; + QUE_T rReOrderQue; + UINT_16 u2WinStart; + UINT_16 u2WinEnd; + UINT_16 u2WinSize; + + /* For identifying the RX BA agreement */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + + BOOLEAN fgIsWaitingForPktWithSsn; + + //UINT_8 ucTxBufferSize; + //BOOL fgIsAcConstrain; + //BOOL fgIsBaEnabled; +} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; + +/* The mailbox message (could be used for Host-To-Device or Device-To-Host Mailbox) */ +typedef struct _MAILBOX_MSG_T{ + UINT_32 u4Msg[2]; /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ +} MAILBOX_MSG_T, *P_MAILBOX_MSG_T; + + +/* Used for adaptively adjusting TC resources */ +typedef struct _TC_RESOURCE_CTRL_T { + /* TC0, TC1, TC2, TC3, TC5 */ + UINT_32 au4AverageQueLen[TC_NUM - 1]; +} TC_RESOURCE_CTRL_T, *P_TC_RESOURCE_CTRL_T; + +typedef struct _QUE_MGT_T{ /* Queue Management Control Info */ + + /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ + QUE_T arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; + +#if 0 + /* For TX Scheduling */ + UINT_8 arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; + UINT_8 arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; + +#endif + + /* Reordering Queue Parameters */ + RX_BA_ENTRY_T arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; + + /* Current number of activated RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS */ + UINT_8 ucRxBaCount; + +#if QM_TEST_MODE + UINT_32 u4PktCount; + P_ADAPTER_T prAdapter; + +#if QM_TEST_FAIR_FORWARDING + UINT_32 u4CurrentStaRecIndexToEnqueue; +#endif + +#endif + + +#if QM_FORWARDING_FAIRNESS + /* The current TX count for a STA with respect to a TC index */ + UINT_32 au4ForwardCount[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving STA with respect to a TC index */ + UINT_32 au4HeadStaRecIndex [NUM_OF_PER_STA_TX_QUEUES]; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 au4AverageQueLen[TC_NUM]; + UINT_32 au4CurrentTcResource[TC_NUM]; + UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ + UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ + + UINT_32 u4TimeToAdjustTcResource; + UINT_32 u4TimeToUpdateQueLen; + + /* Set to TRUE if the last TC adjustment has not been completely applied (i.e., waiting more TX-Done events + to align the TC quotas to the TC resource assignment) */ + BOOLEAN fgTcResourcePostAnnealing; + +#endif + +#if QM_DEBUG_COUNTER + UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif + + + + +} QUE_MGT_T, *P_QUE_MGT_T; + + + +typedef struct _EVENT_RX_ADDBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + + /* Fields that are present in the received ADDBA_REQ */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ + +} EVENT_RX_ADDBA_T, *P_EVENT_RX_ADDBA_T; + +typedef struct _EVENT_RX_DELBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; +} EVENT_RX_DELBA_T, *P_EVENT_RX_DELBA_T; + + +typedef struct _EVENT_BSS_ABSENCE_PRESENCE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucNetTypeIdx; + BOOLEAN fgIsAbsent; + UINT_8 ucBssFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_BSS_ABSENCE_PRESENCE_T, *P_EVENT_BSS_ABSENCE_PRESENCE_T; + + +typedef struct _EVENT_STA_CHANGE_PS_MODE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + BOOLEAN fgIsInPs; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; +} EVENT_STA_CHANGE_PS_MODE_T, *P_EVENT_STA_CHANGE_PS_MODE_T; + +/* The free quota is used by PS only now */ +/* The event may be used by per STA flow conttrol in general */ +typedef struct _EVENT_STA_UPDATE_FREE_QUOTA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_STA_UPDATE_FREE_QUOTA_T, *P_EVENT_STA_UPDATE_FREE_QUOTA_T; + + + + +/* WMM-2.2.1 WMM Information Element */ +typedef struct _IE_WMM_INFO_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucDummy[3]; /* Dummy for pack */ +} IE_WMM_INFO_T, *P_IE_WMM_INFO_T; + +/* WMM-2.2.2 WMM Parameter Element */ +typedef struct _IE_WMM_PARAM_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + + /* IE Body */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + + /* WMM IE Body */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucReserved; + + /* AC Parameters */ + UINT_8 ucAciAifsn_BE; + UINT_8 ucEcw_BE; + UINT_8 aucTxopLimit_BE[2]; + + UINT_8 ucAciAifsn_BG; + UINT_8 ucEcw_BG; + UINT_8 aucTxopLimit_BG[2]; + + UINT_8 ucAciAifsn_VI; + UINT_8 ucEcw_VI; + UINT_8 aucTxopLimit_VI[2]; + + UINT_8 ucAciAifsn_VO; + UINT_8 ucEcw_VO; + UINT_8 aucTxopLimit_VO[2]; + +} IE_WMM_PARAM_T, *P_IE_WMM_PARAM_T; + +typedef struct _IE_WMM_TSPEC_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + /* WMM TSPEC body */ + UINT_8 aucTsInfo[3]; /* TS Info */ + UINT_8 aucTspecBodyPart[1]; /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ +} IE_WMM_TSPEC_T, *P_IE_WMM_TSPEC_T; + +typedef struct _IE_WMM_HDR_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 aucBody[1]; /* IE body */ +} IE_WMM_HDR_T, *P_IE_WMM_HDR_T; + + +typedef struct _AC_QUE_PARMS_T{ + UINT_16 u2CWmin; /*!< CWmin */ + UINT_16 u2CWmax; /*!< CWmax */ + UINT_16 u2TxopLimit; /*!< TXOP limit */ + UINT_16 u2Aifsn; /*!< AIFSN */ + UINT_8 ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ + BOOLEAN fgIsACMSet; +} AC_QUE_PARMS_T, *P_AC_QUE_PARMS_T; + +/* WMM ACI (AC index) */ +typedef enum _ENUM_WMM_ACI_T { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +} ENUM_WMM_ACI_T, *P_ENUM_WMM_ACI_T; + + +/* Used for CMD Queue Operation */ +typedef enum _ENUM_FRAME_ACTION_T { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +} ENUM_FRAME_ACTION_T; + + +typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYEP_NUM +} ENUM_FRAME_TYPE_IN_CMD_Q_T; + +typedef enum _ENUM_FREE_QUOTA_MODET_T { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; + + + +typedef struct _CMD_UPDATE_WMM_PARMS_T { + AC_QUE_PARMS_T arACQueParms[AC_NUM]; + UINT_8 ucNetTypeIndex; + UINT_8 fgIsQBSS; + UINT_8 aucReserved[2]; +} CMD_UPDATE_WMM_PARMS_T, *P_CMD_UPDATE_WMM_PARMS_T; + + +typedef struct _CMD_TX_AMPDU_T { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_TX_AMPDU_T, *P_CMD_TX_AMPDU_T; + + +typedef struct _CMD_ADDBA_REJECT { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_ADDBA_REJECT_T, *P_CMD_ADDBA_REJECT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define QM_TX_SET_NEXT_MSDU_INFO(_prMsduInfoPreceding, _prMsduInfoNext) \ + ((((_prMsduInfoPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prMsduInfoNext)) + +#define QM_TX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) + + +#define QM_TX_GET_NEXT_MSDU_INFO(_prMsduInfo) \ + ((P_MSDU_INFO_T)(((_prMsduInfo)->rQueEntry).prNext)) + +#define QM_RX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) + +#define QM_RX_GET_NEXT_SW_RFB(_prSwRfb) \ + ((P_SW_RFB_T)(((_prSwRfb)->rQueEntry).prNext)) + +#if 0 +#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ + ((((_ucIndex) != STA_REC_INDEX_BMCAST) && ((_ucIndex)!= STA_REC_INDEX_NOT_FOUND)) ?\ + &(_prAdapter->arStaRec[_ucIndex]): NULL) +#endif + +#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ + cnmGetStaRecByIndex(_prAdapter,_ucIndex) + + +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(\ + _prMsduInfo,\ + _ucTC,\ + _ucPacketType,\ + _ucFormatID,\ + _fgIs802_1x,\ + _fgIs802_11,\ + _u2PalLLH,\ + _u2AclSN,\ + _ucPsForwardingType,\ + _ucPsSessionID\ + ) \ +{\ + ASSERT(_prMsduInfo);\ + (_prMsduInfo)->ucTC = (_ucTC);\ + (_prMsduInfo)->ucPacketType = (_ucPacketType);\ + (_prMsduInfo)->ucFormatID = (_ucFormatID);\ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x);\ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11);\ + (_prMsduInfo)->u2PalLLH = (_u2PalLLH);\ + (_prMsduInfo)->u2AclSN = (_u2AclSN);\ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType);\ + (_prMsduInfo)->ucPsSessionID = (_ucPsSessionID);\ + (_prMsduInfo)->fgIsBurstEnd = (FALSE);\ +} + +#define QM_INIT_STA_REC(\ + _prStaRec,\ + _fgIsValid,\ + _fgIsQoS,\ + _pucMacAddr\ + )\ +{\ + ASSERT(_prStaRec);\ + (_prStaRec)->fgIsValid = (_fgIsValid);\ + (_prStaRec)->fgIsQoS = (_fgIsQoS);\ + (_prStaRec)->fgIsInPS = FALSE; \ + (_prStaRec)->ucPsSessionID = 0xFF;\ + COPY_MAC_ADDR((_prStaRec)->aucMacAddr,(_pucMacAddr));\ +} + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +#define QM_GET_TX_QUEUE_LEN(_prAdapter, _u4QueIdx) ((_prAdapter->rQM.au4AverageQueLen[(_u4QueIdx)] >> QM_QUE_LEN_MOVING_AVE_FACTOR)) +#endif + + +#define WMM_IE_OUI_TYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiType) +#define WMM_IE_OUI_SUBTYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiSubtype) +#define WMM_IE_OUI(fp) (((P_IE_WMM_HDR_T)(fp))->aucOui) + +#if QM_DEBUG_COUNTER +#define QM_DBG_CNT_INC(_prQM, _index) { (_prQM)->au4QmDebugCounters[(_index)]++; } +#else +#define QM_DBG_CNT_INC(_prQM, _index) {} +#endif + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Queue Management and STA_REC Initialization */ +/*----------------------------------------------------------------------------*/ + +VOID +qmInit( + IN P_ADAPTER_T prAdapter + ); + +#if QM_TEST_MODE +VOID +qmTestCases( + IN P_ADAPTER_T prAdapter + ); +#endif + +VOID +qmActivateStaRec( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +VOID +qmDeactivateStaRec( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4StaRecIdx + ); + + +/*----------------------------------------------------------------------------*/ +/* TX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +P_MSDU_INFO_T +qmFlushTxQueues( + IN P_ADAPTER_T prAdapter + ); + +P_MSDU_INFO_T +qmFlushStaTxQueues( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4StaRecIdx + ); + +P_MSDU_INFO_T +qmEnqueueTxPackets( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ); + +P_MSDU_INFO_T +qmDequeueTxPackets( + IN P_ADAPTER_T prAdapter, + IN P_TX_TCQ_STATUS_T prTcqStatus + ); + +VOID +qmAdjustTcQuotas ( + IN P_ADAPTER_T prAdapter, + OUT P_TX_TCQ_ADJUST_T prTcqAdjust, + IN P_TX_TCQ_STATUS_T prTcqStatus + ); + + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +VOID +qmReassignTcResource( + IN P_ADAPTER_T prAdapter + ); + +VOID +qmUpdateAverageTxQueLen( + IN P_ADAPTER_T prAdapter + ); +#endif + + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +VOID +qmInitRxQueues( + IN P_ADAPTER_T prAdapter + ); + +P_SW_RFB_T +qmFlushRxQueues( + IN P_ADAPTER_T prAdapter + ); + +P_SW_RFB_T +qmHandleRxPackets( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfbListHead + ); + +VOID +qmProcessPktWithReordering( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT P_QUE_T prReturnedQue + ); + +VOID +qmProcessBarFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT P_QUE_T prReturnedQue + ); + +VOID +qmInsertFallWithinReorderPkt( + IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ); + +VOID +qmInsertFallAheadReorderPkt( + IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ); + +VOID +qmPopOutDueToFallWithin( + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ); + +VOID +qmPopOutDueToFallAhead( + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ); + + +VOID +qmHandleMailboxRxMessage( + IN MAILBOX_MSG_T prMailboxRxMsg + ); + +BOOLEAN +qmCompareSnIsLessThan( + IN UINT_32 u4SnLess, + IN UINT_32 u4SnGreater + ); + +VOID +qmHandleEventRxAddBa( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ); + +VOID +qmHandleEventRxDelBa( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ); + +P_RX_BA_ENTRY_T +qmLookupRxBaEntry( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, + IN UINT_8 ucTid + ); + +BOOL +qmAddRxBaEntry( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, + IN UINT_8 ucTid, + IN UINT_16 u2WinStart, + IN UINT_16 u2WinSize + ); + + +VOID +qmDelRxBaEntry( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, + IN UINT_8 ucTid, + IN BOOLEAN fgFlushToHost + ); + + +VOID +mqmProcessAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength + ); + +VOID +mqmParseEdcaParameters ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + IN BOOLEAN fgForceOverride + ); + +VOID +mqmFillAcQueParam( + IN P_IE_WMM_PARAM_T prIeWmmParam, + IN UINT_32 u4AcOffset, + OUT P_AC_QUE_PARMS_T prAcQueParams + ); + +VOID +mqmProcessScanResult( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prScanResult, + OUT P_STA_RECORD_T prStaRec + ); + + +/* Utility function: for deciding STA-REC index */ +UINT_8 +qmGetStaRecIdx( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucEthDestAddr, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ); + +VOID +mqmGenerateWmmInfoIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +VOID +mqmGenerateWmmParamIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + + +ENUM_FRAME_ACTION_T +qmGetFrameAction( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType +); + +VOID +qmHandleEventBssAbsencePresence( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ); + +VOID +qmHandleEventStaChangePsMode( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ); + +VOID +mqmProcessAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength + ); + +VOID +qmHandleEventStaUpdateFreeQuota( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ); + + +VOID +qmUpdateFreeQuota( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUpdateMode, + IN UINT_8 ucFreeQuota + ); + +VOID +qmFreeAllByNetType( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +UINT_32 +qmGetRxReorderQueuedBufferCount( + IN P_ADAPTER_T prAdapter + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUE_MGT_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h new file mode 100755 index 000000000000..c9a7f184dea8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h @@ -0,0 +1,1012 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/wlan_def.h#1 $ +*/ + +/*! \file "wlan_def.h" + \brief This file includes the basic definition of WLAN + +*/ + + + +/* +** $Log: wlan_def.h $ + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h and let the sw structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 17 2011 yuche.tsai + * NULL + * Resize the Secondary Device Type array when WiFi Direct is enabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Add new station type MACRO. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 11 2010 kevin.huang + * [WCXRP00000068] [MT6620 Wi-Fi][Driver][FW] Fix STA RECORD sync issue and remove unused code + * Update ENUM_STA_ROLE_INDEX_T by using a fixed base value + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 14 2010 chinghwa.yu + * NULL + * Update OP_MODE_BOW and include bow_fsm.h. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * Change P2P Descriptor List to a pointer and allocate it dynamically to avoid structure corrupt by BssDescriptor free. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Add a pointer in BSS Descriptor for P2P Descriptor. + * + * 08 11 2010 yuche.tsai + * NULL + * Add an Interface in BSS Descriptor. + * + * 08 05 2010 yuche.tsai + * NULL + * Modify data structure for P2P Scan result. + * + * 07 26 2010 yuche.tsai + * + * Add an operation mode for P2P device. + * + * 07 23 2010 cp.wu + * + * P2P/RSN/WAPI IEs need to be declared with compact structure. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P present boolean flag in BSS & Pre-BSS descriptor. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * move bss related data types to wlan_def.h to avoid recursive dependency. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:40 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 + +/* The rate definitions */ +#define TX_MODE_CCK 0x00 +#define TX_MODE_OFDM 0x40 +#define TX_MODE_HT_MM 0x80 +#define TX_MODE_HT_GF 0xC0 + +#define RATE_CCK_SHORT_PREAMBLE 0x10 +#define RATE_OFDM 0x20 + +#define PHY_RATE_1M 0x0 +#define PHY_RATE_2M 0x1 +#define PHY_RATE_5_5M 0x2 +#define PHY_RATE_11M 0x3 +#define PHY_RATE_6M 0xB +#define PHY_RATE_9M 0xF +#define PHY_RATE_12M 0xA +#define PHY_RATE_18M 0xE +#define PHY_RATE_24M 0x9 +#define PHY_RATE_36M 0xD +#define PHY_RATE_48M 0x8 +#define PHY_RATE_54M 0xC +#define PHY_RATE_MCS0 0x0 +#define PHY_RATE_MCS1 0x1 +#define PHY_RATE_MCS2 0x2 +#define PHY_RATE_MCS3 0x3 +#define PHY_RATE_MCS4 0x4 +#define PHY_RATE_MCS5 0x5 +#define PHY_RATE_MCS6 0x6 +#define PHY_RATE_MCS7 0x7 +#define PHY_RATE_MCS32 0x20 + +#define RATE_CCK_1M_LONG (TX_MODE_CCK | PHY_RATE_1M) +#define RATE_CCK_2M_LONG (TX_MODE_CCK | PHY_RATE_2M) +#define RATE_CCK_5_5M_LONG (TX_MODE_CCK | PHY_RATE_5_5M) +#define RATE_CCK_11M_LONG (TX_MODE_CCK | PHY_RATE_11M) +#define RATE_CCK_2M_SHORT (TX_MODE_CCK | PHY_RATE_2M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_5_5M_SHORT (TX_MODE_CCK | PHY_RATE_5_5M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_11M_SHORT (TX_MODE_CCK | PHY_RATE_11M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_OFDM_6M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_54M) + +#define RATE_MM_MCS_0 (TX_MODE_HT_MM | PHY_RATE_MCS0) +#define RATE_MM_MCS_1 (TX_MODE_HT_MM | PHY_RATE_MCS1) +#define RATE_MM_MCS_2 (TX_MODE_HT_MM | PHY_RATE_MCS2) +#define RATE_MM_MCS_3 (TX_MODE_HT_MM | PHY_RATE_MCS3) +#define RATE_MM_MCS_4 (TX_MODE_HT_MM | PHY_RATE_MCS4) +#define RATE_MM_MCS_5 (TX_MODE_HT_MM | PHY_RATE_MCS5) +#define RATE_MM_MCS_6 (TX_MODE_HT_MM | PHY_RATE_MCS6) +#define RATE_MM_MCS_7 (TX_MODE_HT_MM | PHY_RATE_MCS7) +#define RATE_MM_MCS_32 (TX_MODE_HT_MM | PHY_RATE_MCS32) + +#define RATE_GF_MCS_0 (TX_MODE_HT_GF | PHY_RATE_MCS0) +#define RATE_GF_MCS_1 (TX_MODE_HT_GF | PHY_RATE_MCS1) +#define RATE_GF_MCS_2 (TX_MODE_HT_GF | PHY_RATE_MCS2) +#define RATE_GF_MCS_3 (TX_MODE_HT_GF | PHY_RATE_MCS3) +#define RATE_GF_MCS_4 (TX_MODE_HT_GF | PHY_RATE_MCS4) +#define RATE_GF_MCS_5 (TX_MODE_HT_GF | PHY_RATE_MCS5) +#define RATE_GF_MCS_6 (TX_MODE_HT_GF | PHY_RATE_MCS6) +#define RATE_GF_MCS_7 (TX_MODE_HT_GF | PHY_RATE_MCS7) +#define RATE_GF_MCS_32 (TX_MODE_HT_GF | PHY_RATE_MCS32) + +#define RATE_TX_MODE_MASK BITS(6,7) +#define RATE_TX_MODE_OFFSET 6 +#define RATE_CODE_GET_TX_MODE(_ucRateCode) ((_ucRateCode & RATE_TX_MODE_MASK) >> RATE_TX_MODE_OFFSET) +#define RATE_PHY_RATE_MASK BITS(0,5) +#define RATE_PHY_RATE_OFFSET 0 +#define RATE_CODE_GET_PHY_RATE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_MASK) >> RATE_PHY_RATE_OFFSET) +#define RATE_PHY_RATE_SHORT_PREAMBLE BIT(4) +#define RATE_CODE_IS_SHORT_PREAMBLE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_SHORT_PREAMBLE)?TRUE:FALSE) + + +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +/*! CNM(STA_RECORD_T) related definition */ +#define CFG_STA_REC_NUM 20 + +/* PHY TYPE bit definitions */ +#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) /* HR/DSSS PHY (clause 18) */ +#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) /* ERP PHY (clause 19) */ +#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) /* OFDM 5 GHz PHY (clause 17) */ +#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) /* HT PHY (clause 20) */ + + +/* PHY TYPE set definitions */ +#define PHY_TYPE_SET_802_11ABGN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11BGN (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11GN (PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11AN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11ABG (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11BG (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11A (PHY_TYPE_BIT_OFDM) + +#define PHY_TYPE_SET_802_11G (PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11B (PHY_TYPE_BIT_HR_DSSS) + +#define PHY_TYPE_SET_802_11N (PHY_TYPE_BIT_HT) + + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_INDEX) /* Bit 13: 54M */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_INDEX) /* Bit 14: BSS Selector */ + + +/* Rate set definitions */ +#define RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_HT (RATE_SET_ERP) +//#define RATE_SET_HT (RATE_SET_ERP | RATE_SET_BIT_HT_PHY) /* NOTE(Kevin): TBD */ + + +#define RATE_SET_ALL_ABG RATE_SET_ERP + +#define BASIC_RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M) + +#define BASIC_RATE_SET_HR_DSSS_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define BASIC_RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_100 RATE_SET_ALL_ABG + +#define INITIAL_RATE_SET_RCPI_80 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_60 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M) + +#define INITIAL_RATE_SET(_rcpi) (INITIAL_RATE_SET_ ## _rcpi) + +#define RCPI_100 100 /* -60 dBm */ +#define RCPI_80 80 /* -70 dBm */ +#define RCPI_60 60 /* -80 dBm */ + + +/* The number of RCPI records used to calculate their average value */ +#define MAX_NUM_RCPI_RECORDS 10 + +/* The number of RCPI records used to calculate their average value */ +#define NO_RCPI_RECORDS -128 +#define MAX_RCPI_DBM 0 +#define MIN_RCPI_DBM -100 + + +#define MAC_TX_RESERVED_FIELD 0 /* NOTE(Kevin): Should defined in tx.h */ + +#define MAX_ASSOC_ID (CFG_STA_REC_NUM) /* Available AID: 1 ~ 20(STA_REC_NUM) */ + + +#define MAX_DEAUTH_INFO_COUNT 4 /* NOTE(Kevin): Used in auth.c */ +#define MIN_DEAUTH_INTERVAL_MSEC 500 /* The minimum interval if continuously send Deauth Frame */ + +/* Authentication Type */ +#define AUTH_TYPE_OPEN_SYSTEM BIT(AUTH_ALGORITHM_NUM_OPEN_SYSTEM) +#define AUTH_TYPE_SHARED_KEY BIT(AUTH_ALGORITHM_NUM_SHARED_KEY) +#define AUTH_TYPE_FAST_BSS_TRANSITION BIT(AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 6 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_16 PHY_TYPE, *P_PHY_TYPE; +typedef UINT_8 RCPI, *P_RCPI; +typedef UINT_8 ALC_VAL, *P_ALC_VAL; + +typedef enum _ENUM_HW_BSSID_T { + BSSID_0 = 0, + BSSID_1, + BSSID_NUM +} ENUM_HW_BSSID_T; + +typedef enum _ENUM_HW_MAC_ADDR_T { + MAC_ADDR_0 = 0, + MAC_ADDR_1, + MAC_ADDR_NUM +} ENUM_HW_MAC_ADDR_T; + +typedef enum _ENUM_HW_OP_MODE_T { + HW_OP_MODE_STA = 0, + HW_OP_MODE_AP, + HW_OP_MODE_ADHOC, + HW_OP_MODE_NUM +} ENUM_HW_OP_MODE_T; + +typedef enum _ENUM_TSF_T { + ENUM_LOCAL_TSF_0, + ENUM_LOCAL_TSF_1, + ENUM_LOCAL_TSF_NUM +} ENUM_LOCAL_TSF_T, *P_ENUM_LOCAL_TSF_T; + +typedef enum _HAL_TS_HW_UPDATE_MODE { + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME, + HAL_TSF_HW_UPDATE_BY_TICK_ONLY, + HAL_TSF_HW_UPDATE_BY_RECEIVED_FRAME_ONLY, + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME_AD_HOC +} HAL_TSF_HW_UPDATE_MODE; + + +typedef enum _ENUM_AC_T { + AC0 = 0, + AC1, + AC2, + AC3, + AC_NUM +} ENUM_AC_T, *P_ENUM_AC_T; + + +/* The Type of Network been activated */ +typedef enum _ENUM_NETWORK_TYPE_INDEX_T { + NETWORK_TYPE_AIS_INDEX = 0, + NETWORK_TYPE_P2P_INDEX, + NETWORK_TYPE_BOW_INDEX, + NETWORK_TYPE_INDEX_NUM +} ENUM_NETWORK_TYPE_INDEX_T; + + +/* The Type of STA Type. */ +typedef enum _ENUM_STA_TYPE_INDEX_T { + STA_TYPE_LEGACY_INDEX = 0, + STA_TYPE_P2P_INDEX, + STA_TYPE_BOW_INDEX, + STA_TYPE_INDEX_NUM +} +ENUM_STA_TYPE_INDEX_T; + +#define STA_ROLE_BASE_INDEX 4 + +typedef enum _ENUM_STA_ROLE_INDEX_T { + STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, //4 + STA_ROLE_CLIENT_INDEX, + STA_ROLE_AP_INDEX, + STA_ROLE_DLS_INDEX +} ENUM_STA_ROLE_INDEX_T; + +/* The Power State of a specific Network */ +typedef enum _ENUM_PWR_STATE_T { + PWR_STATE_IDLE = 0, + PWR_STATE_ACTIVE, + PWR_STATE_PS, + PWR_STATE_NUM +} ENUM_PWR_STATE_T; + +typedef enum _ENUM_PHY_TYPE_INDEX_T { + //PHY_TYPE_DSSS_INDEX, /* DSSS PHY (clause 15) -- Not used anymore */ + PHY_TYPE_HR_DSSS_INDEX = 0, /* HR/DSSS PHY (clause 18) */ + PHY_TYPE_ERP_INDEX, /* ERP PHY (clause 19) */ + PHY_TYPE_ERP_P2P_INDEX, /* ERP PHY (clause 19) w/o HR/DSSS */ + PHY_TYPE_OFDM_INDEX, /* OFDM 5 GHz PHY (clause 17) */ + PHY_TYPE_HT_INDEX, /* HT PHY (clause 20) */ + PHY_TYPE_INDEX_NUM // 5 +} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; + +typedef enum _ENUM_ACPI_STATE_T { + ACPI_STATE_D0 = 0, + ACPI_STATE_D1, + ACPI_STATE_D2, + ACPI_STATE_D3 +} ENUM_ACPI_STATE_T; + +/* The operation mode of a specific Network */ +typedef enum _ENUM_OP_MODE_T { + OP_MODE_INFRASTRUCTURE = 0, /* Infrastructure/GC */ + OP_MODE_IBSS, /* AdHoc */ + OP_MODE_ACCESS_POINT, /* For GO */ + OP_MODE_P2P_DEVICE, /* P2P Device */ + OP_MODE_BOW, + OP_MODE_NUM +} ENUM_OP_MODE_T, *P_ENUM_OP_MODE_T; + +typedef enum _ENUM_CHNL_EXT_T { + CHNL_EXT_SCN = 0, + CHNL_EXT_SCA = 1, + CHNL_EXT_RES = 2, + CHNL_EXT_SCB = 3 +} ENUM_CHNL_EXT_T, *P_ENUM_CHNL_EXT_T; + +/* This starting freq of the band is unit of kHz */ +typedef enum _ENUM_BAND_T { + BAND_NULL, + BAND_2G4, + BAND_5G, + BAND_NUM +} ENUM_BAND_T, *P_ENUM_BAND_T; + +/* Provide supported channel list to other components in array format */ +typedef struct _RF_CHANNEL_INFO_T { + ENUM_BAND_T eBand; + UINT_8 ucChannelNum; +} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_T; + +typedef enum _ENUM_RATE_INDEX_T { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + RATE_22M_INDEX, /* 22M */ + RATE_33M_INDEX, /* 33M */ + RATE_6M_INDEX, /* 6M */ + RATE_9M_INDEX, /* 9M */ + RATE_12M_INDEX, /* 12M */ + RATE_18M_INDEX, /* 18M */ + RATE_24M_INDEX, /* 24M */ + RATE_36M_INDEX, /* 36M */ + RATE_48M_INDEX, /* 48M */ + RATE_54M_INDEX, /* 54M */ + RATE_HT_PHY_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM // 15 +} ENUM_RATE_INDEX_T, *P_ENUM_RATE_INDEX_T; + +typedef enum _ENUM_HT_RATE_INDEX_T { + HT_RATE_MCS0_INDEX = 0, + HT_RATE_MCS1_INDEX, + HT_RATE_MCS2_INDEX, + HT_RATE_MCS3_INDEX, + HT_RATE_MCS4_INDEX, + HT_RATE_MCS5_INDEX, + HT_RATE_MCS6_INDEX, + HT_RATE_MCS7_INDEX, + HT_RATE_MCS32_INDEX, + HT_RATE_NUM // 9 +} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; + +typedef enum _ENUM_PREMABLE_OPTION_T { + PREAMBLE_DEFAULT_LONG_NONE = 0, /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ + PREAMBLE_OPTION_SHORT, /* SHORT mandatory for PHY_TYPE_ERP, SHORT option for PHY_TYPE_HR_DSSS */ + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_OPTION_NUM +} ENUM_PREMABLE_OPTION_T, *P_ENUM_PREMABLE_OPTION_T; + +typedef enum _ENUM_MODULATION_SYSTEM_T { + MODULATION_SYSTEM_CCK = 0, + MODULATION_SYSTEM_OFDM, + MODULATION_SYSTEM_HT20, + MODULATION_SYSTEM_HT40, + MODULATION_SYSTEM_NUM +} ENUM_MODULATION_SYSTEM_T, *P_ENUM_MODULATION_SYSTEM_T; + +typedef enum _ENUM_MODULATION_TYPE_T { + MODULATION_TYPE_CCK_BPSK = 0, + MODULATION_TYPE_QPSK, + MODULATION_TYPE_16QAM, + MODULATION_TYPE_64QAM, + MODULATION_TYPE_NUM +} ENUM_MODULATION_TYPE_T, *P_ENUM_MODULATION_TYPE_T; + +typedef enum _ENUM_PS_FORWARDING_TYPE_T { + PS_FORWARDING_TYPE_NON_PS = 0, + PS_FORWARDING_TYPE_DELIVERY_ENABLED, + PS_FORWARDING_TYPE_NON_DELIVERY_ENABLED, + PS_FORWARDING_MORE_DATA_ENABLED, + PS_FORWARDING_TYPE_NUM +} ENUM_PS_FORWARDING_TYPE_T, *P_ENUM_PS_FORWARDING_TYPE_T; + +typedef struct _DEAUTH_INFO_T { + UINT_8 aucRxAddr[MAC_ADDR_LEN]; + OS_SYSTIME rLastSendTime; +} DEAUTH_INFO_T, *P_DEAUTH_INFO_T; + +/*----------------------------------------------------------------------------*/ +/* Information Element (IE) handlers */ +/*----------------------------------------------------------------------------*/ +typedef VOID (*PFN_APPEND_IE_FUNC)(P_ADAPTER_T, P_MSDU_INFO_T); +typedef VOID (*PFN_HANDLE_IE_FUNC)(P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T); +typedef VOID (*PFN_VERIFY_IE_FUNC)(P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T, PUINT_16); +typedef UINT_32 (*PFN_CALCULATE_VAR_IE_LEN_FUNC)(P_ADAPTER_T, ENUM_NETWORK_TYPE_INDEX_T, P_STA_RECORD_T); + +typedef struct _APPEND_IE_ENTRY_T { + UINT_16 u2EstimatedIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_IE_ENTRY_T, *P_APPEND_IE_ENTRY_T; + +typedef struct _APPEND_VAR_IE_ENTRY_T { + UINT_16 u2EstimatedFixedIELen; /* For Fixed Length */ + PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_VAR_IE_ENTRY_T, *P_APPEND_VAR_IE_ENTRY_T; + +typedef struct _HANDLE_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_HANDLE_IE_FUNC pfnHandleIE; +} HANDLE_IE_ENTRY_T, *P_HANDLE_IE_ENTRY_T; + +typedef struct _VERIFY_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_VERIFY_IE_FUNC pfnVarifyIE; +} VERIFY_IE_ENTRY_T, *P_VERIFY_IE_ENTRY_T; + +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration */ +/*----------------------------------------------------------------------------*/ +typedef enum _ENUM_PARAM_CONNECTION_POLICY_T { + CONNECT_BY_SSID_BEST_RSSI = 0, + CONNECT_BY_SSID_GOOD_RSSI_MIN_CH_LOAD, + CONNECT_BY_SSID_ANY, /* NOTE(Kevin): Needed by WHQL */ + CONNECT_BY_BSSID, + CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ +} ENUM_PARAM_CONNECTION_POLICY_T, *P_ENUM_PARAM_CONNECTION_POLICY_T; + +typedef enum _ENUM_PARAM_PREAMBLE_TYPE_T { + PREAMBLE_TYPE_LONG = 0, + PREAMBLE_TYPE_SHORT, + PREAMBLE_TYPE_AUTO /*!< Try preamble short first, if fail tray preamble long. */ +} ENUM_PARAM_PREAMBLE_TYPE_T, *P_ENUM_PARAM_PREAMBLE_TYPE_T; + +/* This is enum defined for user to select a phy config listed in combo box */ +typedef enum _ENUM_PARAM_PHY_CONFIG_T { + PHY_CONFIG_802_11ABG = 0, /*!< Can associated with 802.11abg AP but without n capability, Scan dual band. */ + PHY_CONFIG_802_11BG, /*!< Can associated with 802_11bg AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11G, /*!< Can associated with 802_11g only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11A, /*!< Can associated with 802_11a only AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11B, /*!< Can associated with 802_11b only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11ABGN, /*!< Can associated with 802.11abgn AP, Scan dual band. */ + PHY_CONFIG_802_11BGN, /*!< Can associated with 802_11bgn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11AN, /*!< Can associated with 802_11an AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11GN, /*!< Can associated with 802_11gn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_NUM // 9 +} ENUM_PARAM_PHY_CONFIG_T, *P_ENUM_PARAM_PHY_CONFIG_T; + +/* This is enum defined for user to select an AP Mode */ +typedef enum _ENUM_PARAM_AP_MODE_T { + AP_MODE_11B = 0, /*!< Create 11b BSS if we support 802.11abg/802.11bg. */ + AP_MODE_MIXED_11BG, /*!< Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G, /*!< Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G_P2P, /*!< Create 11g only BSS for P2P if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11A, /*!< Create 11a only BSS if we support 802.11abg. */ + AP_MODE_NUM // 4 +} ENUM_PARAM_AP_MODE_T, *P_ENUM_PARAM_AP_MODE_T; + + +/* Masks for determining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define NETWORK_TYPE_AIS_MASK BIT(NETWORK_TYPE_AIS_INDEX) +#define NETWORK_TYPE_P2P_MASK BIT(NETWORK_TYPE_P2P_INDEX) +#define NETWORK_TYPE_BOW_MASK BIT(NETWORK_TYPE_BOW_INDEX) +#define STA_TYPE_LEGACY_MASK BIT(STA_TYPE_LEGACY_INDEX) +#define STA_TYPE_P2P_MASK BIT(STA_TYPE_P2P_INDEX) +#define STA_TYPE_BOW_MASK BIT(STA_TYPE_BOW_INDEX) +#define STA_TYPE_ADHOC_MASK BIT(STA_ROLE_ADHOC_INDEX) +#define STA_TYPE_CLIENT_MASK BIT(STA_ROLE_CLIENT_INDEX) +#define STA_TYPE_AP_MASK BIT(STA_ROLE_AP_INDEX) +#define STA_TYPE_DLS_MASK BIT(STA_ROLE_DLS_INDEX) + +/* Macros for obtaining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define IS_STA_IN_AIS(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) +#define IS_STA_IN_P2P(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) +#define IS_STA_IN_BOW(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) +#define IS_STA_LEGACY_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_LEGACY_MASK) +#define IS_STA_P2P_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_P2P_MASK) +#define IS_STA_BOW_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_BOW_MASK) +#define IS_ADHOC_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_ADHOC_MASK) +#define IS_CLIENT_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_CLIENT_MASK) +#define IS_AP_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_AP_MASK) +#define IS_DLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_DLS_MASK) + +/* The ENUM_STA_TYPE_T accounts for ENUM_NETWORK_TYPE_T and ENUM_STA_ROLE_INDEX_T. + * * It is a merged version of Network Type and STA Role. + * */ +typedef enum _ENUM_STA_TYPE_T { + STA_TYPE_LEGACY_AP = (STA_TYPE_LEGACY_MASK | STA_TYPE_AP_MASK), + STA_TYPE_LEGACY_CLIENT = (STA_TYPE_LEGACY_MASK | STA_TYPE_CLIENT_MASK), + STA_TYPE_ADHOC_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_ADHOC_MASK), +#if CFG_ENABLE_WIFI_DIRECT + STA_TYPE_P2P_GO = (STA_TYPE_P2P_MASK | STA_TYPE_AP_MASK), + STA_TYPE_P2P_GC = (STA_TYPE_P2P_MASK | STA_TYPE_CLIENT_MASK), +#endif +#if CFG_ENABLE_BT_OVER_WIFI + STA_TYPE_BOW_AP = (STA_TYPE_BOW_MASK | STA_TYPE_AP_MASK), + STA_TYPE_BOW_CLIENT = (STA_TYPE_BOW_MASK | STA_TYPE_CLIENT_MASK), +#endif + STA_TYPE_DLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_DLS_MASK) +} ENUM_STA_TYPE_T, *P_ENUM_STA_TYPE_T; + +/* The type of BSS we discovered */ +typedef enum _ENUM_BSS_TYPE_T { + BSS_TYPE_INFRASTRUCTURE = 1, + BSS_TYPE_IBSS, + BSS_TYPE_P2P_DEVICE, + BSS_TYPE_BOW_DEVICE, + BSS_TYPE_NUM +} ENUM_BSS_TYPE_T, *P_ENUM_BSS_TYPE_T; + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +//#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +//#pragma pack(1) +//#endif + +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 8 /* max number of supported cipher suites */ +#if CFG_SUPPORT_802_11W +#define MAX_NUM_SUPPORTED_AKM_SUITES 8 /* max number of supported AKM suites */ +#else +#define MAX_NUM_SUPPORTED_AKM_SUITES 6 /* max number of supported AKM suites */ +#endif + +/* Structure of RSN Information */ +typedef struct _RSN_INFO_T { + UINT_8 ucElemId; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_32 u4PairwiseKeyCipherSuiteCount; + UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + UINT_32 u4AuthKeyMgtSuiteCount; + UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_AKM_SUITES]; + UINT_16 u2RsnCap; + BOOLEAN fgRsnCapPresent; +} /*__KAL_ATTRIB_PACKED__*/ RSN_INFO_T, *P_RSN_INFO_T; + +#define MAX_NUM_SUPPORTED_WAPI_AKM_SUITES 1 /* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES 1 /* max number of supported cipher suites */ + +/* Structure of WAPI Information */ +typedef struct _WAPI_INFO_T { + UINT_8 ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_32 u4AuthKeyMgtSuiteCount; + UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_WAPI_AKM_SUITES]; + UINT_32 u4PairwiseKeyCipherSuiteCount; + UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES]; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2WapiCap; + UINT_16 u2Bkid; + UINT_8 aucBkid[1][16]; +} /* __KAL_ATTRIB_PACKED__*/ WAPI_INFO_T, *P_WAPI_INFO_T; + +//#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +//#pragma pack() +//#endif + + +#if CFG_ENABLE_WIFI_DIRECT + +typedef struct _P2P_DEVICE_TYPE_T { + UINT_16 u2CategoryID; + UINT_16 u2SubCategoryID; +} P2P_DEVICE_TYPE_T, *P_P2P_DEVICE_TYPE_T; + +typedef struct _P2P_DEVICE_DESC_T { + LINK_ENTRY_T rLinkEntry; + BOOLEAN fgDevInfoValid; + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Interface Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method support. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[8]; // Reference to P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT + UINT_16 u2NameLength; + UINT_8 aucName[32]; // Reference to WPS_ATTRI_MAX_LEN_DEVICE_NAME + // TODO: Service Information or PasswordID valid? +} P2P_DEVICE_DESC_T, *P_P2P_DEVICE_DESC_T; + +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static const UINT_8 aucRateIndex2RateCode[PREAMBLE_OPTION_NUM][RATE_NUM] = { + { /* Long Preamble */ + RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ + RATE_CCK_2M_LONG, /* RATE_2M_INDEX */ + RATE_CCK_5_5M_LONG, /* RATE_5_5M_INDEX */ + RATE_CCK_11M_LONG, /* RATE_11M_INDEX */ + RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ + RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ + RATE_OFDM_6M, /* RATE_6M_INDEX */ + RATE_OFDM_9M, /* RATE_9M_INDEX */ + RATE_OFDM_12M, /* RATE_12M_INDEX */ + RATE_OFDM_18M, /* RATE_18M_INDEX */ + RATE_OFDM_24M, /* RATE_24M_INDEX */ + RATE_OFDM_36M, /* RATE_36M_INDEX */ + RATE_OFDM_48M, /* RATE_48M_INDEX */ + RATE_OFDM_54M, /* RATE_54M_INDEX */ + }, + { /* Short Preamble */ + RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ + RATE_CCK_2M_SHORT, /* RATE_2M_INDEX */ + RATE_CCK_5_5M_SHORT, /* RATE_5_5M_INDEX */ + RATE_CCK_11M_SHORT, /* RATE_11M_INDEX */ + RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ + RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ + RATE_OFDM_6M, /* RATE_6M_INDEX */ + RATE_OFDM_9M, /* RATE_9M_INDEX */ + RATE_OFDM_12M, /* RATE_12M_INDEX */ + RATE_OFDM_18M, /* RATE_18M_INDEX */ + RATE_OFDM_24M, /* RATE_24M_INDEX */ + RATE_OFDM_36M, /* RATE_36M_INDEX */ + RATE_OFDM_48M, /* RATE_48M_INDEX */ + RATE_OFDM_54M, /* RATE_54M_INDEX */ + }, + { /* Mixed Mode(Option) */ + RATE_MM_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_MM_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_MM_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_MM_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_MM_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_MM_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_MM_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_MM_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_MM_MCS_32 /* RATE_MCS32_INDEX, */ + }, + { /* Green Field(Option) */ + RATE_GF_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_GF_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_GF_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_GF_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_GF_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_GF_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_GF_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_GF_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_GF_MCS_32 /* RATE_MCS32_INDEX, */ + } +}; + +static const UINT_8 aucRateTableSize[PREAMBLE_OPTION_NUM] = { + RATE_HT_PHY_INDEX, + RATE_HT_PHY_INDEX, + HT_RATE_NUM, + HT_RATE_NUM +}; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Macros to get and set the wireless LAN frame fields those are 16/32 bits in + length. */ +#define WLAN_GET_FIELD_16(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_16)(_value_p) = ((UINT_16) __cp[0]) | ((UINT_16) __cp[1] << 8); \ + } + +#define WLAN_GET_FIELD_BE16(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_16)(_value_p) = ((UINT_16) __cp[0] << 8) | ((UINT_16) __cp[1]); \ + } + +#define WLAN_GET_FIELD_32(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_32) __cp[0]) | ((UINT_32) __cp[1] << 8) | \ + ((UINT_32) __cp[2] << 16) | ((UINT_32) __cp[3] << 24); \ + } + +#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_64)(_value_p) = \ + ((UINT_64) __cp[0]) | ((UINT_64) __cp[1] << 8) | \ + ((UINT_64) __cp[2] << 16) | ((UINT_64) __cp[3] << 24) | \ + ((UINT_64) __cp[4] << 32) | ((UINT_64) __cp[5] << 40) | \ + ((UINT_64) __cp[6] << 48) | ((UINT_64) __cp[7] << 56); \ + } + +#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + } + +#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) ((_value) >> 8); \ + __cp[1] = (UINT_8) (_value); \ + } + +#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + __cp[2] = (UINT_8) ((_value) >> 16); \ + __cp[3] = (UINT_8) ((_value) >> 24); \ + } + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_DEF_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h new file mode 100755 index 000000000000..17cb03d35209 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h @@ -0,0 +1,1892 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_cmd_event.h#1 $ +*/ + +/*! \file "nic_cmd_event.h" + \brief This file contains the declairation file of the WLAN OID processing routines + of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: nic_cmd_event.h $ + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 04 2012 eason.tsai + * NULL + * modify the cal fail report code. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * redefine the CMD_ID_SET_TXPWR_CTRL value. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 11 30 2011 cm.chang + * [WCXRP00001128] [MT5931 Wi-Fi][FW] Update BB/RF setting based on RF doc v0.7 for LGE spec + * 1. Add a new CMD for driver to set device mode + * 2. Update calibration parameters + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add TX_DONE status detail information. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 10 26 2011 cp.wu + * [WCXRP00001065] [MT6620 Wi-Fi][MT5931][FW][DRV] Adding parameter for controlling minimum channel dwell time for scanning + * add interface for control minimum channel dwell time for scanning. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * New CMD definition about RLM parameters + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 09 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC[WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * add osc stable time command structure + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 31 2011 chinglan.wang + * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. + * . + * + * 03 18 2011 cm.chang + * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command + * As CR title + * + * 03 17 2011 yarco.yang + * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 10 2011 cp.wu + * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers + * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Update cmd format of BSS INFO, always sync OwnMac to FW no matter P2P is enabled or not.. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Sync HT operation element information from host to FW + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition + * follow-up for CMD_5G_PWR_OFFSET_T definition change + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 15 2010 cm.chang + * NULL + * Add new CMD for TX power, 5G power offset and power parameters + * + * 09 07 2010 yuche.tsai + * NULL + * Add a pointer in P2P SCAN RESULT structure. This pointer + * is pointed to a IE buffer for this P2p device. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 george.huang + * NULL + * add new CMD ID definition + * + * 08 16 2010 yuche.tsai + * NULL + * Add a field in BSS INFO cmd to change interface address for P2P. (switching between Device Addr & Interface Addr) + * + * 08 12 2010 yuche.tsai + * NULL + * Add interface address indication when indicate connection status. + * It is requested by supplicant to do 4 way handshake. + * + * 08 07 2010 wh.su + * NULL + * adding the privacy related code for P2P network + * + * 08 05 2010 yuche.tsai + * NULL + * Change data structure for P2P Device scan result, all channel time for scan command. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 28 2010 cp.wu + * NULL + * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. + * + * 07 26 2010 yuche.tsai + * + * Add P2P Device Found Event. + * Channel extention option in scan abort command. + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 20 2010 george.huang + * + * DWORD align for the CMD data structure + * + * 07 20 2010 cp.wu + * + * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 09 2010 cp.wu + * + * reorder members of CMD_SET_BSS_INFO. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * update prStaRecOfAP with BSS-INFO. + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 28 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add BSS/STA_REC commands for integration. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add TX Done Event handle entry + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sync statistics data structure definition with firmware implementation + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * the frequency is used for adhoc connection only + * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list + * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 15 2010 kevin.huang + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Add event for activate STA_RECORD_T + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c + * 'cause it involves OS dependent data structure handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * 4. correct some HAL implementation + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * OID_802_11_RSSI, + * * * OID_802_11_RSSI_TRIGGER, + * * * OID_802_11_STATISTICS, + * * * OID_802_11_DISASSOCIATE, + * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * and result is retrieved by get ATInfo instead + * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-12-11 18:35:07 GMT mtk02752 +** add CMD added in CMD/EVEN document v0.8 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-12-10 16:39:37 GMT mtk02752 +** eliminate unused definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-12-10 09:55:11 GMT mtk02752 +** command ID/event ID revised +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-09 13:57:37 GMT MTK02468 +** Added event ids (EVENT_ID_RX_ADDBA and EVENT_ID_RX_DELBA) +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-08 17:35:39 GMT mtk02752 +** + add event ID for EVENT_ID_TEST_STATUS (rf test) +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-12-07 23:01:09 GMT mtk02752 +** add data structure for RF_TEST +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-12-03 16:22:56 GMT mtk01461 +** Modify the element - i4RSSI in EVENT of SCAN RESULT +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-30 10:54:44 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T, while 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-26 10:16:58 GMT mtk02752 +** resync EVENT_CONNECTION_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-25 21:34:01 GMT mtk02752 +** sync. EVENT_SCAN_RESULT_T with firmware +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-25 21:03:48 GMT mtk02752 +** refine MGMT_FRAME +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-25 18:17:47 GMT mtk02752 +** refine GL_WLAN_INFO_T for buffering scan result and presume max. ie length = 600 bytes +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 22:41:20 GMT mtk02752 +** add EVENT_SCAN_RESULT_T definition +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-11-23 20:29:16 GMT mtk02752 +** fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-11-23 14:46:01 GMT mtk02752 +** add new command/event structure upon CM@SD1's documentation +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-13 15:13:40 GMT mtk02752 +** add command definition for CMD_BUILD_CONNECTION and EVENT_CONNECTION_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-20 12:22:22 GMT mtk01461 +** Add SeqNum field to Event Header +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:11 GMT mtk01461 +** Update structure of HIF_EVENT_HEADER_T and EVENT_HDR_SIZE +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 12:10:36 GMT mtk01461 +** Add Common Set CMD Callback for MCR Write and other Set OID +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:17 GMT mtk01461 +** Command Done Handler +*/ +#ifndef _NIC_CMD_EVENT_H +#define _NIC_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CMD_STATUS_SUCCESS 0 +#define CMD_STATUS_REJECTED 1 +#define CMD_STATUS_UNKNOWN 2 + +#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) + +#define MAX_IE_LENGTH (600) +#define MAX_WSC_IE_LENGTH (400) + +/* Action field in structure CMD_CH_PRIVILEGE_T */ +#define CMD_CH_ACTION_REQ 0 +#define CMD_CH_ACTION_ABORT 1 + +/* Status field in structure EVENT_CH_PRIVILEGE_T */ +#define EVENT_CH_STATUS_GRANT 0 + + +typedef enum _ENUM_CMD_ID_T { + CMD_ID_TEST_MODE = 1, /* 0x01 (Set) */ + CMD_ID_RESET_REQUEST, /* 0x02 (Set) */ + CMD_ID_BUILD_CONNECTION, /* 0x03 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x04 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x05 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x06 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x07 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x08 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x09 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x0a (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0b (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0c (Set) */ + CMD_ID_WIFI_START, /* 0x0d (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0e (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0f (Set) */ + CMD_ID_SEND_ADDBA_RSP, /* 0x10 (Set) */ + CMD_ID_WAPI_MODE, /* 0x11 (Set) (obsolete) */ + CMD_ID_WAPI_ASSOC_INFO, /* 0x12 (Set) (obsolete) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x13 (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x14 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x15 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x16 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x17 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x18 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x19 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x1a (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x1b (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x1c (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x1d (Set) */ + CMD_ID_SCAN_REQ, /* 0x1e (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1f (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x20 (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x21 (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x22 (Set) */ + CMD_ID_TX_AMPDU, /* 0x23 (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x24 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x25 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x26 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x27 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x28 (Set) */ + CMD_ID_SET_5G_PWR_OFFSET, /* 0x29 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x2A (Set) */ + CMD_ID_P2P_ABORT, /* 0x2B (Set) */ +#if CFG_STRESS_TEST_SUPPORT + CMD_ID_RANDOM_RX_RESET_EN = 0x2C, /* 0x2C (Set ) */ + CMD_ID_RANDOM_RX_RESET_DE = 0x2D, /* 0x2D (Set ) */ + CMD_ID_SAPP_EN = 0x2E, /* 0x2E (Set ) */ + CMD_ID_SAPP_DE = 0x2F, /* 0x2F (Set ) */ +#endif + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL = 0x3A, /* 0x3A (Set) */ + + CMD_ID_GET_NIC_CAPABILITY = 0x80, /* 0x80 (Query) */ + CMD_ID_GET_LINK_QUALITY, /* 0x81 (Query) */ + CMD_ID_GET_STATISTICS, /* 0x82 (Query) */ + CMD_ID_GET_CONNECTION_STATUS, /* 0x83 (Query) */ + CMD_ID_GET_ASSOC_INFO, /* 0x84 (Query) (obsolete) */ + CMD_ID_GET_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + + CMD_ID_BASIC_CONFIG = 0xc1, /* 0xc1 (Set / Query) */ + CMD_ID_ACCESS_REG, /* 0xc2 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc3 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc4 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc5 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc6 (Set / Query) */ +#if 1/* CFG_SUPPORT_ANTI_PIRACY */ + CMD_ID_SEC_CHECK, /* 0xc7 (Set / Query) */ +#endif + CMD_ID_DUMP_MEM, /* 0xc8 (Query) */ + +#if CFG_SUPPORT_RDD_TEST_MODE + CMD_ID_SET_RDD_CH = 0xE1, +#endif + + CMD_ID_SET_BWCS = 0xF1, +#if CFG_SUPPORT_OSC_SETTING && defined(MT5931) + CMD_ID_SET_OSC = 0xf2, +#endif + +} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; + +typedef enum _ENUM_EVENT_ID_T { + EVENT_ID_CMD_RESULT = 1, /* 0x01 (Query) */ + EVENT_ID_NIC_CAPABILITY, /* 0x02 (Query) */ + EVENT_ID_CONNECTION_STATUS, /* 0x03 (Query / Unsolicited) (obsolete) */ + EVENT_ID_SCAN_RESULT, /* 0x04 (Query / Unsolicited) (obselete) */ + EVENT_ID_LINK_QUALITY, /* 0x05 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x06 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_ASSOC_INFO, /* 0x08 (Query - CMD_ID_GET_ASSOC_INFO) */ + EVENT_ID_BASIC_CONFIG, /* 0x09 (Query - CMD_ID_BASIC_CONFIG) */ + EVENT_ID_ACCESS_REG, /* 0x0a (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_MAC_MCAST_ADDR, /* 0x0b (Query - CMD_ID_MAC_MCAST_ADDR) */ + EVENT_ID_802_11_PMKID, /* 0x0c (Query - CMD_ID_802_11_PMKID) */ + EVENT_ID_ACCESS_EEPROM, /* 0x0d (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_NOTIFY, /* 0x0e (Query) */ + EVENT_ID_BT_OVER_WIFI, /* 0x0f (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x10 (Query - CMD_ID_TEST_MODE) */ + EVENT_ID_RX_ADDBA, /* 0x11 (Unsolicited) (obsolete) */ + EVENT_ID_RX_DELBA, /* 0x12 (Unsolicited) (obsolete) */ + EVENT_ID_ACTIVATE_STA_REC_T, /* 0x13 (Unsolicited) */ + EVENT_ID_DEACTIVATE_STA_REC_T, /* 0x14 (Unsolicited) */ + EVENT_ID_SCAN_DONE, /* 0x15 (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x16 (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x17 (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x18 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE = 0x19, /* 0x19 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x1A (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x1B (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x1C (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x1D (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x1E (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x1F (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x20 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x21 (Unsolicited) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + EVENT_ID_SEC_CHECK_RSP, /* 0x22 (Unsolicited) */ +#endif + EVENT_ID_SEND_DEAUTH, /* 0x23 (Unsolicited) */ + +#if CFG_SUPPORT_RDD_TEST_MODE + EVENT_ID_UPDATE_RDD_STATUS, /* 0x24 (Unsolicited) */ +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + EVENT_ID_UPDATE_BWCS_STATUS = 0x25, /* 0x25 (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x26 (Unsolicited) */ +#endif + EVENT_ID_RX_ERR, + EVENT_ID_DUMP_MEM, + EVENT_ID_STA_STATISTICS= 0x29, /* 0x29 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE /* 0x2A (Unsolicited) */ +} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef LINUX +typedef UINT_8 CMD_STATUS; +#endif +/* for Event Packet (via HIF-RX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_CMD_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucCID; + UINT_8 ucSetQuery; + UINT_8 ucSeqNum; + UINT_8 aucReserved2; + + UINT_8 aucBuffer[0]; +} WIFI_CMD_T, *P_WIFI_CMD_T; + +/* for Command Packet (via HIF-TX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_EVENT_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + UINT_8 aucBuffer[0]; +} WIFI_EVENT_T, *P_WIFI_EVENT_T; + +// CMD_ID_TEST_MODE +typedef struct _CMD_TEST_CTRL_T { + UINT_8 ucAction; + UINT_8 aucReserved[3]; + union { + UINT_32 u4OpMode; + UINT_32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUC_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + +// EVENT_TEST_STATUS +typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T { + UINT_32 u4PktSentStatus; + UINT_32 u4PktSentCount; + UINT_16 u2AvgAlc; + UINT_8 ucCckGainControl; + UINT_8 ucOfdmGainControl; +} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T; + +typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T { + UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ + UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ + UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ + UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ + UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ + UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ + UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ + UINT_32 u4PauCCACount; /*!< CCA rising edge count */ +} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T; + +typedef union _EVENT_TEST_STATUS { + PARAM_MTK_WIFI_TEST_STRUC_T rATInfo; +// PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T rTxStatus; +// PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T rRxStatus; +} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; + +// CMD_BUILD_CONNECTION +typedef struct _CMD_BUILD_CONNECTION { + UINT_8 ucInfraMode; + UINT_8 ucAuthMode; + UINT_8 ucEncryptStatus; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + UINT_16 u2BeaconPeriod; + UINT_16 u2ATIMWindow; + UINT_8 ucJoinOnly; + UINT_8 ucReserved; + UINT_32 u4FreqInKHz; + + /* for faster connection */ + UINT_8 aucScanResult[0]; +} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; + +//CMD_ADD_REMOVE_KEY +typedef struct _CMD_802_11_KEY { + UINT_8 ucAddRemove; + UINT_8 ucTxKey; + UINT_8 ucKeyType; + UINT_8 ucIsAuthenticator; + UINT_8 aucPeerAddr[6]; + UINT_8 ucNetType; + UINT_8 ucAlgorithmId; + UINT_8 ucKeyId; + UINT_8 ucKeyLen; + UINT_8 aucReverved[2]; + UINT_8 aucKeyMaterial[32]; + UINT_8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; + +/* WPA2 PMKID cache structure */ +typedef struct _PMKID_ENTRY_T { + PARAM_BSSID_INFO_T rBssidInfo; + BOOLEAN fgPmkidExist; +} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; + +typedef struct _CMD_802_11_PMKID +{ + ULONG u4BSSIDInfoCount; + P_PMKID_ENTRY_T arPMKIDInfo[1]; +} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; + +// CMD_BASIC_CONFIG +typedef struct _CMD_CSUM_OFFLOAD { + UINT_16 u2RxChecksum; // bit0: IP, bit1: UDP, bit2: TCP + UINT_16 u2TxChecksum; // bit0: IP, bit1: UDP, bit2: TCP +} CMD_CSUM_OFFLOAD, *P_CMD_CSUM_OFFLOAD; + +typedef struct _CMD_BASIC_CONFIG { + PARAM_MAC_ADDRESS rMyMacAddr; + UINT_8 ucNative80211; + UINT_8 aucReserved[1]; + + CMD_CSUM_OFFLOAD rCsumOffload; +} CMD_BASIC_CONFIG, *P_CMD_BASIC_CONFIG, EVENT_BASIC_CONFIG, *P_EVENT_BASIC_CONFIG; + +// CMD_MAC_MCAST_ADDR +typedef struct _CMD_MAC_MCAST_ADDR { + UINT_32 u4NumOfGroupAddr; + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; + PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; +} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; + +// CMD_ACCESS_EEPROM +typedef struct _CMD_ACCESS_EEPROM { + UINT_16 u2Offset; + UINT_16 u2Data; +} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; + +typedef struct _CMD_CUSTOM_NOA_PARAM_STRUC_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} CMD_CUSTOM_NOA_PARAM_STRUC_T, *P_CMD_CUSTOM_NOA_PARAM_STRUC_T; + +typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUC_T { + UINT_32 u4CTwindowMs; +} CMD_CUSTOM_OPPPS_PARAM_STRUC_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUC_T; + +typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUC_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} CMD_CUSTOM_UAPSD_PARAM_STRUC_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUC_T; + +// EVENT_CONNECTION_STATUS +typedef struct _EVENT_CONNECTION_STATUS { + UINT_8 ucMediaStatus; + UINT_8 ucReasonOfDisconnect; + + UINT_8 ucInfraMode; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + UINT_8 ucAuthenMode; + UINT_8 ucEncryptStatus; + UINT_16 u2BeaconPeriod; + UINT_16 u2AID; + UINT_16 u2ATIMWindow; + UINT_8 ucNetworkType; + UINT_8 aucReserved[1]; + UINT_32 u4FreqInKHz; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; +#endif + +} EVENT_CONNECTION_STATUS, *P_EVENT_CONNECTION_STATUS; + +// EVENT_NIC_CAPABILITY +typedef struct _EVENT_NIC_CAPABILITY { + UINT_16 u2ProductID; + UINT_16 u2FwVersion; + UINT_16 u2DriverVersion; + UINT_8 ucHw5GBandDisabled; + UINT_8 ucEepromUsed; + UINT_8 ucEfuseValid; + UINT_8 ucMacAddrValid; +#if CFG_REPORT_RFBB_VERSION + UINT_8 ucRfVersion; + UINT_8 ucPhyVersion; +#endif +#if CFG_ENABLE_CAL_LOG + UINT_8 ucRfCalFail; + UINT_8 ucBbCalFail; +#endif + UINT_8 aucReserved[2]; +} EVENT_NIC_CAPABILITY, *P_EVENT_NIC_CAPABILITY; + +// modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering +typedef struct _WLAN_BEACON_FRAME_BODY_T_LOCAL { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[MAX_IE_LENGTH]; /* Various IEs, start from SSID */ + UINT_16 u2IELength; /* This field is *NOT* carried by F/W but caculated by nic_rx */ +} WLAN_BEACON_FRAME_BODY_T_LOCAL, *P_WLAN_BEACON_FRAME_BODY_T_LOCAL; + +// EVENT_SCAN_RESULT +typedef struct _EVENT_SCAN_RESULT_T { + INT_32 i4RSSI; + UINT_32 u4LinkQuality; + UINT_32 u4DSConfig; /* Center frequency */ + UINT_32 u4DomainInfo; /* Require CM opinion */ + UINT_32 u4Reserved; + UINT_8 ucNetworkType; + UINT_8 ucOpMode; + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; +} EVENT_SCAN_RESULT_T, *P_EVENT_SCAN_RESULT_T; + +/* event of tkip mic error */ +typedef struct _EVENT_MIC_ERR_INFO +{ + UINT_32 u4Flags; +} EVENT_MIC_ERR_INFO, *P_EVENT_MIC_ERR_INFO; + +typedef struct _EVENT_PMKID_CANDIDATE_LIST_T +{ + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; + + +typedef struct _EVENT_CMD_RESULT { + UINT_8 ucCmdID; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; + +#if CFG_SUPPORT_OSC_SETTING && defined(MT5931) +typedef struct _CMD_MCU_LP_PARAM_T { + UINT_16 u2OscStableTime; + UINT_8 ucReserved[6]; +} CMD_MCU_LP_PARAM_T, *P_CMD_MCU_LP_PARAM_T; +#endif + + +// CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG +typedef struct _CMD_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; + +// CMD_DUMP_MEMORY +typedef struct _CMD_DUMP_MEM { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} CMD_DUMP_MEM, *P_CMD_DUMP_MEM; + +typedef struct _EVENT_DUMP_MEM_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; + UINT_8 aucBuffer[1]; +} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; + +typedef struct _CMD_SW_DBG_CTRL_T { + UINT_32 u4Id; + UINT_32 u4Data; + /* Debug Support */ + UINT_32 u4DebugCnt[64]; +} CMD_SW_DBG_CTRL_T, *P_CMD_SW_DBG_CTRL_T; + + +// CMD_ID_LINK_ATTRIB +typedef struct _CMD_LINK_ATTRIB { + INT_8 cRssiTrigger; + UINT_8 ucDesiredRateLen; + UINT_16 u2DesiredRate[32]; + UINT_8 ucMediaStreamMode; + UINT_8 aucReserved[1]; +} CMD_LINK_ATTRIB, *P_CMD_LINK_ATTRIB; + +// CMD_ID_NIC_POWER_CTRL +typedef struct _CMD_NIC_POWER_CTRL { + UINT_8 ucPowerMode; + UINT_8 aucReserved[3]; +} CMD_NIC_POWER_CTRL, *P_CMD_NIC_POWER_CTRL; + +// CMD_ID_POWER_SAVE_MODE +typedef struct _CMD_PS_PROFILE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucPsProfile; + UINT_8 aucReserved[2]; +} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; + + +// EVENT_LINK_QUALITY +typedef struct _EVENT_LINK_QUALITY { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; +} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; + +#if CFG_SUPPORT_P2P_RSSI_QUERY +// EVENT_LINK_QUALITY +typedef struct _EVENT_LINK_QUALITY_EX { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; + UINT_8 ucIsLQ0Rdy; + INT_8 cRssiP2P; /* For P2P Network. */ + INT_8 cLinkQualityP2P; + UINT_16 u2LinkSpeedP2P; + UINT_8 ucMediumBusyPercentageP2P; + UINT_8 ucIsLQ1Rdy; +} EVENT_LINK_QUALITY_EX, *P_EVENT_LINK_QUALITY_EX; +#endif + +// EVENT_ID_STATISTICS +typedef struct _EVENT_STATISTICS { + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; +} EVENT_STATISTICS, *P_EVENT_STATISTICS; + +// EVENT_ID_FW_SLEEPY_NOTIFY +typedef struct _EVENT_SLEEPY_NOTIFY { + UINT_8 ucSleepyState; + UINT_8 aucReserved[3]; +} EVENT_SLEEPY_NOTIFY, *P_EVENT_SLEEPY_NOTIFY; + +typedef struct _EVENT_ACTIVATE_STA_REC_T { + UINT_8 aucMacAddr[6]; + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + BOOLEAN fgIsQoS; + BOOLEAN fgIsAP; + UINT_8 aucReserved[2]; +} EVENT_ACTIVATE_STA_REC_T, *P_EVENT_ACTIVATE_STA_REC_T; + +typedef struct _EVENT_DEACTIVATE_STA_REC_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_DEACTIVATE_STA_REC_T, *P_EVENT_DEACTIVATE_STA_REC_T; + +// CMD_BT_OVER_WIFI +typedef struct _CMD_BT_OVER_WIFI { + UINT_8 ucAction; /* 0: query, 1: setup, 2: destroy */ + UINT_8 ucChannelNum; + PARAM_MAC_ADDRESS rPeerAddr; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 PAL_Capabilities; + UINT_8 cMaxTxPower; + UINT_8 ucChannelBand; + UINT_8 ucReserved[1]; +} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI; + +// EVENT_BT_OVER_WIFI +typedef struct _EVENT_BT_OVER_WIFI { + UINT_8 ucLinkStatus; + UINT_8 ucSelectedChannel; + INT_8 cRSSI; + UINT_8 ucReserved[1]; +} EVENT_BT_OVER_WIFI, *P_EVENT_BT_OVER_WIFI; + +// Same with DOMAIN_SUBBAND_INFO +typedef struct _CMD_SUBBAND_INFO { + UINT_8 ucRegClass; + UINT_8 ucBand; + UINT_8 ucChannelSpan; + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 aucReserved[3]; +} CMD_SUBBAND_INFO, *P_CMD_SUBBAND_INFO; + +// CMD_SET_DOMAIN_INFO +typedef struct _CMD_SET_DOMAIN_INFO_T { + UINT_16 u2CountryCode; + UINT_16 u2Reserved; + CMD_SUBBAND_INFO rSubBand[6]; + + UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 aucReserved[2]; +} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; + +// CMD_SET_IP_ADDRESS +typedef struct _IPV4_NETWORK_ADDRESS { + UINT_8 aucIpAddr[4]; +} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; + +typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { + UINT_8 ucNetTypeIndex; + UINT_8 ucAddressCount; + UINT_8 ucReserved[2]; + IPV4_NETWORK_ADDRESS arNetAddress[1]; +} CMD_SET_NETWORK_ADDRESS_LIST, *P_CMD_SET_NETWORK_ADDRESS_LIST; + +typedef struct _PATTERN_DESCRIPTION { + UINT_8 fgCheckBcA1; + UINT_8 fgCheckMcA1; + UINT_8 ePatternHeader; + UINT_8 fgAndOp; + UINT_8 fgNotOp; + UINT_8 ucPatternMask; + UINT_16 ucPatternOffset; + UINT_8 aucPattern[8]; +} PATTERN_DESCRIPTION, *P_PATTERN_DESCRIPTION; + +typedef struct _CMD_RAW_PATTERN_CONFIGURATION_T { + PATTERN_DESCRIPTION arPatternDesc[4]; +} CMD_RAW_PATTERN_CONFIGURATION_T, *P_CMD_RAW_PATTERN_CONFIGURATION_T; + +typedef struct _CMD_PATTERN_FUNC_CONFIG { + BOOLEAN fgBcA1En; + BOOLEAN fgMcA1En; + BOOLEAN fgBcA1MatchDrop; + BOOLEAN fgMcA1MatchDrop; +} CMD_PATTERN_FUNC_CONFIG, *P_CMD_PATTERN_FUNC_CONFIG; + + +typedef struct _EVENT_TX_DONE_T { + UINT_8 ucPacketSeq; + UINT_8 ucStatus; + UINT_16 u2SequenceNumber; + UINT_32 au4Reserved1; + UINT_32 au4Reserved2; + UINT_32 au4Reserved3; +} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; + +typedef struct _CMD_BSS_ACTIVATE_CTRL { + UINT_8 ucNetTypeIndex; + UINT_8 ucActive; + UINT_8 aucReserved[2]; +} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; + +typedef struct _CMD_SET_BSS_RLM_PARAM_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucRfBand; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucErpProtectMode; + UINT_8 ucHtProtectMode; + UINT_8 ucGfOperationMode; + UINT_8 ucTxRifsMode; + UINT_16 u2HtOpInfo3; + UINT_16 u2HtOpInfo2; + UINT_8 ucHtOpInfo1; + UINT_8 ucUseShortPreamble; + UINT_8 ucUseShortSlotTime; + UINT_8 ucCheckId; /* Fixed value: 0x72 */ +} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; + +typedef struct _CMD_SET_BSS_INFO { + UINT_8 ucNetTypeIndex; + UINT_8 ucConnectionState; + UINT_8 ucCurrentOPMode; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + UINT_8 aucBSSID[6]; + UINT_8 ucIsQBSS; + UINT_8 ucReserved1; + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucStaRecIdxOfAP; + UINT_8 ucReserved2; + UINT_8 ucReserved3; + UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + UINT_8 ucAuthMode; + UINT_8 ucEncStatus; + UINT_8 ucPhyTypeSet; + UINT_8 aucOwnMac[6]; + UINT_8 fgWapiMode; + UINT_8 fgIsApMode; + UINT_8 aucRsv[1]; + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; +} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; + +typedef struct _CMD_UPDATE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucStaType; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_16 u2AssocId; + UINT_16 u2ListenInterval; + UINT_8 ucNetTypeIndex; + UINT_8 ucDesiredPhyTypeSet; + UINT_16 u2DesiredNonHTRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucIsQoS; + UINT_8 ucIsUapsdSupported; + UINT_8 ucStaState; + UINT_8 ucMcsSet; + UINT_8 ucSupMcs32; + UINT_8 ucAmpduParam; + UINT_16 u2HtCapInfo; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; + UINT_8 ucRCPI; + UINT_8 ucNeedResp; + UINT_8 ucUapsdAc; /* b0~3: Trigger enabled, b4~7: Delivery enabled */ + UINT_8 ucUapsdSp; /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ + UINT_8 aucReserved[3]; + /* TBD */ +} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; + +typedef struct _CMD_REMOVE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucReserved; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; + +typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 aucReserved[2]; +} CMD_INDICATE_PM_BSS_CREATED, *P_CMD_INDICATE_PM_BSS_CREATED; + +typedef struct _CMD_INDICATE_PM_BSS_CONNECTED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2AssocId; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 fgIsUapsdConnection; + UINT_8 ucBmpDeliveryAC; + UINT_8 ucBmpTriggerAC; + UINT_8 aucReserved[1]; +} CMD_INDICATE_PM_BSS_CONNECTED, *P_CMD_INDICATE_PM_BSS_CONNECTED; + +typedef struct _CMD_INDICATE_PM_BSS_ABORT { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; +} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; + +typedef struct _CMD_BEACON_TEMPLATE_UPDATE { + UINT_8 ucUpdateMethod; // 0: update randomly, 1: update all, 2: delete all (1 and 2 will update directly without search) + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_16 u2Capability; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; + +typedef struct _CMD_SET_WMM_PS_TEST_STRUC_T { + UINT_8 ucNetTypeIndex; + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +} CMD_SET_WMM_PS_TEST_STRUC_T, *P_CMD_SET_WMM_PS_TEST_STRUC_T; + + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +typedef struct _CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNum; +} CHANNEL_INFO_T, *P_CHANNEL_INFO_T; + +typedef struct _CMD_SCAN_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucReserved[1]; + UINT_16 u2ChannelMinDwellTime; + UINT_8 aucSSID[32]; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ, *P_CMD_SCAN_REQ; + +typedef struct _CMD_SCAN_REQ_V2_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[4]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; + +typedef struct _CMD_SCAN_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucIsExtChannel; /* For P2P channel extention. */ + UINT_8 aucReserved[2]; +} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; + +typedef struct _EVENT_SCAN_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucSparseChannelValid; + CHANNEL_INFO_T rSparseChannel; +} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucAction; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucBSSID[6]; + UINT_8 aucReserved[2]; +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + +typedef struct _CMD_TX_PWR_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ +#if defined(MT6620) + INT_8 acReserved[3]; +#elif defined(MT5931) || defined(MT6628) + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; +#else + #error "No valid definition!" +#endif + + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} CMD_TX_PWR_T, *P_CMD_TX_PWR_T; + +typedef struct _CMD_5G_PWR_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; + +typedef struct _CMD_PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; + + +typedef struct _CMD_PHY_PARAM_T { + UINT_8 aucData[144]; /* eFuse content */ +} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; + +typedef struct _CMD_AUTO_POWER_PARAM_T { + UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change paramters */ + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 aucLevelRcpiTh[3]; + UINT_8 aucReserved2[1]; + INT_8 aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ + UINT_8 aucReserved3[1]; + UINT_8 aucReserved4[8]; +} CMD_AUTO_POWER_PARAM_T, *P_CMD_AUTO_POWER_PARAM_T; + + +typedef struct _EVENT_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucStatus; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4GrantInterval; /* In unit of ms */ +} EVENT_CH_PRIVILEGE_T, *P_EVENT_CH_PRIVILEGE_T; + +typedef struct _EVENT_BSS_BEACON_TIMEOUT_T { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; +} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; + +typedef struct _EVENT_STA_AGING_TIMEOUT_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; + +typedef struct _EVENT_NOA_TIMING_T { + UINT_8 fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} EVENT_NOA_TIMING_T, *P_EVENT_NOA_TIMING_T; + +typedef struct _EVENT_UPDATE_NOA_PARAMS_T { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 fgEnableOppPS; + UINT_16 u2CTWindow; + + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + EVENT_NOA_TIMING_T arEventNoaTiming[8/*P2P_MAXIMUM_NOA_COUNT*/]; +} EVENT_UPDATE_NOA_PARAMS_T, *P_EVENT_UPDATE_NOA_PARAMS_T; + +typedef struct _EVENT_AP_OBSS_STATUS_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucObssErpProtectMode; + UINT_8 ucObssHtProtectMode; + UINT_8 ucObssGfOperationMode; + UINT_8 ucObssRifsOperationMode; + UINT_8 ucObssBeaconForcedTo20M; + UINT_8 aucReserved[2]; +} EVENT_AP_OBSS_STATUS_T, *P_EVENT_AP_OBSS_STATUS_T; + +typedef struct _CMD_EDGE_TXPWR_LIMIT_T { + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + INT_8 cReserved; +} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; + +typedef struct _CMD_SET_DEVICE_MODE_T { + UINT_16 u2ChipID; + UINT_16 u2Mode; +} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; + + +#if CFG_SUPPORT_RDD_TEST_MODE +typedef struct _CMD_RDD_CH_T { + UINT_8 ucRddTestMode; + UINT_8 ucRddShutCh; + UINT_8 ucRddStartCh; + UINT_8 ucRddStopCh; + UINT_8 ucRddDfs; + UINT_8 ucReserved; + UINT_8 ucReserved1; + UINT_8 ucReserved2; +} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; + +typedef struct _EVENT_RDD_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; +} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; +#endif + +typedef struct _CMD_SET_TXPWR_CTRL_T{ + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0*/ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0*/ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence + in the same channel + 0: Highest power has priority + 1: Lowest power has priority */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm*/ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} CMD_SET_TXPWR_CTRL_T, *P_CMD_SET_TXPWR_CTRL_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID +nicCmdEventQueryMcrRead ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryMemDump ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQuerySwCtrlRead ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + + + +VOID +nicCmdEventQueryRfTestATInfo( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventSetCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventSetDisassociate ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventSetIpAddress ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryLinkQuality( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryStatistics( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventEnterRfTest( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventLeaveRfTest( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryAddress( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryMcastAddr( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryEepromRead( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventSetMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +/* Statistics responder */ +VOID +nicCmdEventQueryXmitOk( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryRecvOk( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryXmitError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryRecvError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryRecvNoBuffer( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryRecvCrcError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryRecvErrorAlignment( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryXmitOneCollision( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryXmitMoreCollisions( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +nicCmdEventQueryXmitMaxCollisions( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +/* for timeout check */ +VOID +nicOidCmdTimeoutCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +VOID +nicCmdTimeoutCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +VOID +nicOidCmdEnterRFTestTimeout ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_CMD_EVENT_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h new file mode 100755 index 000000000000..33886c98045a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h @@ -0,0 +1,180 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_init_cmd_event.h#1 $ +*/ + +/*! \file "nic_init_cmd_event.h" + \brief This file contains the declairation file of the WLAN initialization routines + for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: nic_init_cmd_event.h $ + * + * 09 26 2011 cp.wu + * [WCXRP00001011] [MT6628 Wi-Fi] Firmware Download Agent: make CRC validation as an optional feature + * add definition for disabling CRC32 validation (for MT6628 only) + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add command/event definitions for initial states + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * +*/ +#ifndef _NIC_INIT_CMD_EVENT_H +#define _NIC_INIT_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define INIT_CMD_STATUS_SUCCESS 0 +#define INIT_CMD_STATUS_REJECTED_INVALID_PARAMS 1 +#define INIT_CMD_STATUS_REJECTED_CRC_ERROR 2 +#define INIT_CMD_STATUS_REJECTED_DECRYPT_FAIL 3 +#define INIT_CMD_STATUS_UNKNOWN 4 + +#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) + +typedef enum _ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_BUF = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR +} ENUM_INIT_CMD_ID, *P_ENUM_INIT_CMD_ID; + +typedef enum _ENUM_INIT_EVENT_ID { + INIT_EVENT_ID_CMD_RESULT = 1, + INIT_EVENT_ID_ACCESS_REG, + INIT_EVENT_ID_PENDING_ERROR +} ENUM_INIT_EVENT_ID, *P_ENUM_INIT_EVENT_ID; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_8 CMD_STATUS; + +// commands +typedef struct _INIT_WIFI_CMD_T { + UINT_8 ucCID; + UINT_8 ucSeqNum; + UINT_16 u2Reserved; + UINT_8 aucBuffer[0]; +} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; + +typedef struct _INIT_HIF_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + INIT_WIFI_CMD_T rInitWifiCmd; +} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; + +#define DOWNLOAD_BUF_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_BUF_NO_CRC_CHECKING BIT(30) +#define DOWNLOAD_BUF_ACK_OPTION BIT(31) +typedef struct _INIT_CMD_DOWNLOAD_BUF { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4CRC32; + UINT_32 u4DataMode; + UINT_8 aucBuffer[0]; +} INIT_CMD_DOWNLOAD_BUF, *P_INIT_CMD_DOWNLOAD_BUF; + +typedef struct _INIT_CMD_WIFI_START { + UINT_32 u4Override; + UINT_32 u4Address; +} INIT_CMD_WIFI_START, *P_INIT_CMD_WIFI_START; + +typedef struct _INIT_CMD_ACCESS_REG { + UINT_8 ucSetQuery; + UINT_8 aucReserved[3]; + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_CMD_ACCESS_REG, *P_INIT_CMD_ACCESS_REG; + +// Events +typedef struct _INIT_WIFI_EVENT_T { + UINT_16 u2RxByteCount; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucBuffer[0]; +} INIT_WIFI_EVENT_T, *P_INIT_WIFI_EVENT_T; + +typedef struct _INIT_HIF_RX_HEADER_T { + INIT_WIFI_EVENT_T rInitWifiEvent; +} INIT_HIF_RX_HEADER_T, *P_INIT_HIF_RX_HEADER_T; + +typedef struct _INIT_EVENT_CMD_RESULT { + UINT_8 ucStatus; // 0: success + // 1: rejected by invalid param + // 2: rejected by incorrect CRC + // 3: rejected by decryption failure + // 4: unknown CMD + UINT_8 aucReserved[3]; +} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_INIT_CMD_EVENT_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h new file mode 100755 index 000000000000..892b5b714baf --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h @@ -0,0 +1,225 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/p2p_precomp.h#1 $ +*/ + +/*! \file p2p_precomp.h + \brief Collection of most compiler flags for p2p driver are described here. + + In this file we collect all compiler flags and detail the p2p driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + + + +#ifndef _P2P_PRECOMP_H +#define _P2P_PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" // Include "config.h" + +#include "gl_p2p_os.h" + +#include "debug.h" + +#include "link.h" +#include "queue.h" + + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ +#include "wlan_typedef.h" + + +#include "mac.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "wlan_def.h" + +#include "roaming_fsm.h" + + +/*------------------------------------------------------------------------------ + * .\include\nic + *------------------------------------------------------------------------------ + */ +/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ +#include "cmd_buf.h" + + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "nic_cmd_event.h" + + +/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ +#include "nic.h" + +#include "nic_init_cmd_event.h" + +#include "hif_rx.h" +#include "hif_tx.h" + +#include "nic_tx.h" + +/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ +#include "nic_rx.h" + +#include "que_mgt.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#include "wlan_p2p.h" + + + + +#include "hal.h" + +#if defined(MT6620) + #include "mt6620_reg.h" +#elif defined(MT5931) + #include "mt5931_reg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" + + +#include "aa_fsm.h" + +#include "cnm_timer.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +/* Dependency: cnm_timer.h (TIMER_T) */ +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" + + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + + +#include "ais_fsm.h" + + +#include "adapter.h" + + +#include "que_mgt.h" +#include "rftest.h" + + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#include "gl_p2p_kal.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_PRECOMP_H */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h new file mode 100755 index 000000000000..c8aa47fb6297 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h @@ -0,0 +1,278 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/p2p_typedef.h#1 $ +*/ + +/*! \file p2p_typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to all MGMT Protocol Stack. +*/ + + + + +#ifndef _P2P_TYPEDEF_H +#define _P2P_TYPEDEF_H + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* +* type definition of pointer to p2p structure +*/ +//typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; +typedef struct _P2P_INFO_T P2P_INFO_T, *P_P2P_INFO_T; + +typedef struct _P2P_FSM_INFO_T P2P_FSM_INFO_T, *P_P2P_FSM_INFO_T; + +typedef struct _P2P_CONNECTION_SETTINGS_T P2P_CONNECTION_SETTINGS_T, *P_P2P_CONNECTION_SETTINGS_T; + + +/* Type definition for function pointer to p2p function*/ +typedef BOOLEAN (*P2P_LAUNCH)( + P_GLUE_INFO_T prGlueInfo + ); + +typedef BOOLEAN (*P2P_REMOVE)( + P_GLUE_INFO_T prGlueInfo, + BOOLEAN fgIsWlanLaunched + ); + +typedef BOOLEAN (*KAL_P2P_GET_CIPHER)( + IN P_GLUE_INFO_T prGlueInfo + ); + +typedef BOOLEAN (*KAL_P2P_GET_TKIP_CIPHER)( + IN P_GLUE_INFO_T prGlueInfo + ); + +typedef BOOLEAN (*KAL_P2P_GET_CCMP_CIPHER)( + IN P_GLUE_INFO_T prGlueInfo + ); + +typedef BOOLEAN (*KAL_P2P_GET_WSC_MODE)( + IN P_GLUE_INFO_T prGlueInfo + ); + +typedef struct net_device* (*KAL_P2P_GET_DEV_HDLR)( + P_GLUE_INFO_T prGlueInfo + ); + +typedef VOID (*KAL_P2P_SET_MULTICAST_WORK_ITEM) ( + P_GLUE_INFO_T prGlueInfo + ); + +typedef VOID (*P2P_NET_REGISTER) ( + P_GLUE_INFO_T prGlueInfo + ); + +typedef VOID (*P2P_NET_UNREGISTER) ( + P_GLUE_INFO_T prGlueInfo + ); + +typedef VOID (*KAL_P2P_UPDATE_ASSOC_INFO)( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, + IN BOOLEAN fgReassocRequest + ); + +typedef BOOLEAN (*P2P_VALIDATE_AUTH) ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PP_STA_RECORD_T pprStaRec, + OUT PUINT_16 pu2StatusCode + ); + +typedef BOOLEAN (*P2P_VALIDATE_ASSOC_REQ) ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu4ControlFlags + ); + +typedef VOID (*P2P_RUN_EVENT_AAA_TX_FAIL) ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +typedef BOOLEAN (*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM)( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, + OUT PUINT_8 pucOuiType + ); + + +typedef WLAN_STATUS (*P2P_RUN_EVENT_AAA_COMPLETE) ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +typedef VOID (*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam + ); + +typedef VOID (*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, + IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame + ); + +typedef VOID (*P2P_RX_PUBLIC_ACTION_FRAME) ( + P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + +typedef VOID (*RLM_RSP_GENERATE_OBSS_SCAN_IE) ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ); + +typedef VOID (*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP)( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +typedef VOID (*RLM_PROCESS_PUBLIC_ACTION)( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ); + +typedef VOID (*RLM_PROCESS_HT_ACTION)( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ); + +typedef VOID (*RLM_UPDATE_PARAMS_FOR_AP)( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + BOOLEAN fgUpdateBeacon + ); + +typedef VOID (*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) ( + P_ADAPTER_T prAdapter, + P_EVENT_AP_OBSS_STATUS_T prObssStatus + ); + + +typedef BOOLEAN (*P2P_FUNC_VALIDATE_PROBE_REQ) ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ); + +typedef VOID (*RLM_BSS_INIT_FOR_AP)( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +typedef UINT_32 (*P2P_GET_PROB_RSP_IE_TABLE_SIZE)( + VOID + ); + +typedef PUINT_8 (*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucBuffer + ); + + +typedef VOID (*P2P_FUNC_DISCONNECT) ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN BOOLEAN fgSendDeauth, + IN UINT_16 u2ReasonCode + ); + +typedef VOID (*P2P_FSM_RUN_EVENT_RX_DEAUTH) ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ); + +typedef VOID (*P2P_FSM_RUN_EVENT_RX_DISASSOC) ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ); + +typedef BOOLEAN (*P2P_FUN_IS_AP_MODE) ( + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ); + +typedef VOID (*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) ( + IN P_ADAPTER_T prAdapter + ); + + +typedef VOID (*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); + + +typedef VOID (*P2P_GENERATE_P2P_IE) ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +typedef UINT_32 (*P2P_CALCULATE_P2P_IE_LEN) ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ); + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /*CFG_ENABLE_WIFI_DIRECT*/ + +#endif /* _P2P_TYPEDEF_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h new file mode 100755 index 000000000000..0e5a8e372076 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h @@ -0,0 +1,380 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/precomp.h#2 $ +*/ + +/*! \file precomp.h + \brief Collection of most compiler flags are described here. + + In this file we collect all compiler flags and detail the driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + + + +/* +** $Log: precomp.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Isolate P2P related function for Hardware Software Bundle + * + * 09 14 2010 chinghwa.yu + * NULL + * Fix BOW_FSM_INFO_T dependence. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 11:30:58 GMT mtk02752 +** add rftest.h for implementing RF test mode in driver land +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-23 22:02:00 GMT mtk02468 +** Added que_mgt.h +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-13 21:58:36 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:40:11 GMT mtk01461 +** Add nic_cmd_event.h +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 20:00:26 GMT mtk01461 +** Add cmd_buf.h +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:44 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:25 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:38 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" // Include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +#include "debug.h" + +#include "link.h" +#include "queue.h" + + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ +#include "wlan_typedef.h" + +#include "mac.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "wlan_def.h" + +#if CFG_SUPPORT_SWCR +#include "swcr.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\nic + *------------------------------------------------------------------------------ + */ +/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ +#include "cmd_buf.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "nic_cmd_event.h" + +/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ +#include "nic.h" + +#include "nic_init_cmd_event.h" + +#include "hif_rx.h" +#include "hif_tx.h" + +#include "nic_tx.h" + +/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ +#include "nic_rx.h" + +#include "que_mgt.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#if defined(MT6620) + #include "mt6620_reg.h" +#elif defined(MT5931) + #include "mt5931_reg.h" +#elif defined(MT6628) + #include "mt6628_reg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#if CFG_SUPPORT_802_11V +#include "wnm.h" +#endif + +#include "aa_fsm.h" + +#include "cnm_timer.h" + + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#endif + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + +#if CFG_SUPPORT_ROAMING +#include "roaming_fsm.h" +#endif /* CFG_SUPPORT_ROAMING */ + +#include "ais_fsm.h" + + +#include "adapter.h" + + +#include "que_mgt.h" +#include "rftest.h" + + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRECOMP_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h new file mode 100755 index 000000000000..4819de0fd9bb --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h @@ -0,0 +1,147 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/pwr_mgt.h#1 $ +*/ + +/*! \file "pwr_mgt.h" + \brief In this file we define the STATE and EVENT for Power Management FSM. + + The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter + ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail + description. +*/ + + + +/* +** $Log: pwr_mgt.h $ + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL + * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. + + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load adress & start address are now configured from config.h + * * * due to the different configurations on FPGA and ASIC +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-10 16:39:10 GMT mtk02752 +** disable PM macros temporally +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-29 19:48:37 GMT mtk01084 +** temp remove power management macro +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-08 16:51:11 GMT mtk01084 +** update for power management control macro +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-03 14:59:58 GMT mtk01426 +** Add #if CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:53:10 GMT mtk01084 +** modify ACQUIRE_POWER_CONTROL_FROM_PM() and RECLAIM_POWER_CONTROL_TO_PM() macro +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:32:47 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:20 GMT mtk01084 +** Initial version +** +*/ + +#ifndef _PWR_MGT_H +#define _PWR_MGT_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PM_UAPSD_AC0 (BIT(0)) +#define PM_UAPSD_AC1 (BIT(1)) +#define PM_UAPSD_AC2 (BIT(2)) +#define PM_UAPSD_AC3 (BIT(3)) + +#define PM_UAPSD_ALL (PM_UAPSD_AC0 | PM_UAPSD_AC1 | PM_UAPSD_AC2 | PM_UAPSD_AC3) +#define PM_UAPSD_NONE 0 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PM_PROFILE_SETUP_INFO_T { + /* Profile setup */ + UINT_8 ucBmpDeliveryAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + UINT_8 ucBmpTriggerAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + + UINT_8 ucUapsdSp; /* Number of triggered packets in UAPSD */ + +} PM_PROFILE_SETUP_INFO_T, *P_PM_PROFILE_SETUP_INFO_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if !CFG_ENABLE_FULL_PM + #define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) + #define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) +#else + #define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) \ + { \ + if (_prAdapter->fgIsFwOwn) { \ + nicpmSetDriverOwn(_prAdapter); \ + } \ + /* Increase Block to Enter Low Power Semaphore count */ \ + GLUE_INC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + } + + #define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + ASSERT(_prAdapter->u4PwrCtrlBlockCnt != 0); \ + /* Decrease Block to Enter Low Power Semaphore count */ \ + GLUE_DEC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + if (_prAdapter->fgWiFiInSleepyState && (_prAdapter->u4PwrCtrlBlockCnt == 0)) { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } \ + } +#endif + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PWR_MGT_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h new file mode 100755 index 000000000000..a7773e9d592d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h @@ -0,0 +1,189 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/queue.h#1 $ +*/ + +/*! \file queue.h + \brief Definition for singly queue operations. + + In this file we define the singly queue data structure and its + queue operation MACROs. +*/ + + + +/* +** $Log: queue.h $ + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:46 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _QUEUE_H +#define _QUEUE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Singly Queue Structures - Entry Part */ +typedef struct _QUE_ENTRY_T { + struct _QUE_ENTRY_T *prNext; + struct _QUE_ENTRY_T *prPrev; /* For Rx buffer reordering used only */ +} QUE_ENTRY_T, *P_QUE_ENTRY_T; + +/* Singly Queue Structures - Queue Part */ +typedef struct _QUE_T { + P_QUE_ENTRY_T prHead; + P_QUE_ENTRY_T prTail; + UINT_32 u4NumElem; +} QUE_T, *P_QUE_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define QUEUE_INITIALIZE(prQueue) \ + { \ + (prQueue)->prHead = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->u4NumElem = 0; \ + } + +#define QUEUE_IS_EMPTY(prQueue) (((P_QUE_T)(prQueue))->prHead == (P_QUE_ENTRY_T)NULL) + +#define QUEUE_IS_NOT_EMPTY(prQueue) ((prQueue)->u4NumElem > 0) + +#define QUEUE_GET_HEAD(prQueue) ((prQueue)->prHead) + +#define QUEUE_GET_TAIL(prQueue) ((prQueue)->prTail) + +#define QUEUE_GET_NEXT_ENTRY(prQueueEntry) ((prQueueEntry)->prNext) + +#define QUEUE_INSERT_HEAD(prQueue, prQueueEntry) \ + { \ + ASSERT(prQueue); \ + ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (prQueue)->prHead; \ + (prQueue)->prHead = (prQueueEntry); \ + if ((prQueue)->prTail == (P_QUE_ENTRY_T)NULL) { \ + (prQueue)->prTail = (prQueueEntry); \ + } \ + ((prQueue)->u4NumElem)++; \ + } + +#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ + { \ + ASSERT(prQueue); \ + ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (P_QUE_ENTRY_T)NULL; \ + if ((prQueue)->prTail) { \ + ((prQueue)->prTail)->prNext = (prQueueEntry); \ + } else { \ + (prQueue)->prHead = (prQueueEntry); \ + } \ + (prQueue)->prTail = (prQueueEntry); \ + ((prQueue)->u4NumElem)++; \ + } + +/* NOTE: We assume the queue entry located at the beginning of "prQueueEntry Type", + * so that we can cast the queue entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define QUEUE_REMOVE_HEAD(prQueue, prQueueEntry, _P_TYPE) \ + { \ + ASSERT(prQueue); \ + prQueueEntry = (_P_TYPE)((prQueue)->prHead); \ + if (prQueueEntry) { \ + (prQueue)->prHead = ((P_QUE_ENTRY_T)(prQueueEntry))->prNext; \ + if ((prQueue)->prHead == (P_QUE_ENTRY_T)NULL){ \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + } \ + ((P_QUE_ENTRY_T)(prQueueEntry))->prNext = (P_QUE_ENTRY_T)NULL; \ + ((prQueue)->u4NumElem)--; \ + } \ + } + +#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + *(P_QUE_T)prDestQueue = *(P_QUE_T)prSrcQueue; \ + QUEUE_INITIALIZE(prSrcQueue); \ + } + +#define QUEUE_CONCATENATE_QUEUES(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + if (prSrcQueue->u4NumElem > 0) { \ + if ((prDestQueue)->prTail) { \ + ((prDestQueue)->prTail)->prNext = (prSrcQueue)->prHead; \ + } else { \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + } \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUEUE_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h new file mode 100755 index 000000000000..ae6541dc2e92 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h @@ -0,0 +1,317 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/rftest.h#1 $ +*/ + +/*! \file "rftest.h" + \brief definitions for RF Productino test + +*/ + + + +/* +** $Log: rftest.h $ + * + * 12 20 2011 cp.wu + * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information + * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO + * to expose version information + * + * 08 04 2010 cp.wu + * NULL + * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-08 17:35:11 GMT mtk02752 +** * comment out RF test which is not supported on MT6620 +** + API decalre for rftest +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-12-08 11:29:07 GMT mtk02752 +** definitions for RF test mode +** +*/ +#ifndef _RFTEST_H +#define _RFTEST_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +// Table Version +#define RF_AUTO_TEST_FUNCTION_TABLE_VERSION 0x01000001 + +// Power +#define RF_AT_PARAM_POWER_MASK BITS(0,7) +#define RF_AT_PARAM_POWER_MAX RF_AT_PARAM_POWER_MASK + +// Rate +#define RF_AT_PARAM_RATE_MCS_MASK BIT(31) +#define RF_AT_PARAM_RATE_MASK BITS(0,7) +#define RF_AT_PARAM_RATE_CCK_MAX 3 +#define RF_AT_PARAM_RATE_1M 0 +#define RF_AT_PARAM_RATE_2M 1 +#define RF_AT_PARAM_RATE_5_5M 2 +#define RF_AT_PARAM_RATE_11M 3 +#define RF_AT_PARAM_RATE_6M 4 +#define RF_AT_PARAM_RATE_9M 5 +#define RF_AT_PARAM_RATE_12M 6 +#define RF_AT_PARAM_RATE_18M 7 +#define RF_AT_PARAM_RATE_24M 8 +#define RF_AT_PARAM_RATE_36M 9 +#define RF_AT_PARAM_RATE_48M 10 +#define RF_AT_PARAM_RATE_54M 11 + +// Antenna +#define RF_AT_PARAM_ANTENNA_ID_MASK BITS(0,7) +#define RF_AT_PARAM_ANTENNA_ID_MAX 1 + +// Packet Length +#define RF_AT_PARAM_TX_80211HDR_BYTE_MAX (32) +#define RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX (2048) + +#define RF_AT_PARAM_TX_PKTLEN_BYTE_DEFAULT 1024 +#define RF_AT_PARAM_TX_PKTLEN_BYTE_MAX \ + ((UINT_16)(RF_AT_PARAM_TX_80211HDR_BYTE_MAX + RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX )) + +// Packet Count +#define RF_AT_PARAM_TX_PKTCNT_DEFAULT 1000 +#define RF_AT_PARAM_TX_PKTCNT_UNLIMITED 0 + +// Packet Interval +#define RF_AT_PARAM_TX_PKT_INTERVAL_US_DEFAULT 50 + +// ALC +#define RF_AT_PARAM_ALC_DISABLE 0 +#define RF_AT_PARAM_ALC_ENABLE 1 + +// TXOP +#define RF_AT_PARAM_TXOP_DEFAULT 0 +#define RF_AT_PARAM_TXOPQUE_QMASK BITS(16,31) +#define RF_AT_PARAM_TXOPQUE_TMASK BITS(0,15) +#define RF_AT_PARAM_TXOPQUE_AC0 (0<<16) +#define RF_AT_PARAM_TXOPQUE_AC1 (1<<16) +#define RF_AT_PARAM_TXOPQUE_AC2 (2<<16) +#define RF_AT_PARAM_TXOPQUE_AC3 (3<<16) +#define RF_AT_PARAM_TXOPQUE_AC4 (4<<16) +#define RF_AT_PARAM_TXOPQUE_QOFFSET 16 + +// Retry Limit +#define RF_AT_PARAM_TX_RETRY_DEFAULT 0 +#define RF_AT_PARAM_TX_RETRY_MAX 6 + +// QoS Queue +#define RF_AT_PARAM_QOSQUE_AC0 0 +#define RF_AT_PARAM_QOSQUE_AC1 1 +#define RF_AT_PARAM_QOSQUE_AC2 2 +#define RF_AT_PARAM_QOSQUE_AC3 3 +#define RF_AT_PARAM_QOSQUE_AC4 4 +#define RF_AT_PARAM_QOSQUE_DEFAULT RF_AT_PARAM_QOSQUE_AC0 + +// Bandwidth +#define RF_AT_PARAM_BANDWIDTH_20MHZ 0 +#define RF_AT_PARAM_BANDWIDTH_40MHZ 1 +#define RF_AT_PARAM_BANDWIDTH_U20_IN_40MHZ 2 +#define RF_AT_PARAM_BANDWIDTH_D20_IN_40MHZ 3 +#define RF_AT_PARAM_BANDWIDTH_DEFAULT RF_AT_PARAM_BANDWIDTH_20MHZ + +// GI (Guard Interval) +#define RF_AT_PARAM_GI_800NS 0 +#define RF_AT_PARAM_GI_400NS 1 +#define RF_AT_PARAM_GI_DEFAULT RF_AT_PARAM_GI_800NS + +// STBC +#define RF_AT_PARAM_STBC_DISABLE 0 +#define RF_AT_PARAM_STBC_ENABLE 1 + +// RIFS +#define RF_AT_PARAM_RIFS_DISABLE 0 +#define RF_AT_PARAM_RIFS_ENABLE 1 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +// Function ID List +typedef enum _ENUM_RF_AT_FUNCID_T { + RF_AT_FUNCID_VERSION = 0, + RF_AT_FUNCID_COMMAND, + RF_AT_FUNCID_POWER, + RF_AT_FUNCID_RATE, + RF_AT_FUNCID_PREAMBLE, + RF_AT_FUNCID_ANTENNA, + RF_AT_FUNCID_PKTLEN, + RF_AT_FUNCID_PKTCNT, + RF_AT_FUNCID_PKTINTERVAL, + RF_AT_FUNCID_TEMP_COMPEN, + RF_AT_FUNCID_TXOPLIMIT, + RF_AT_FUNCID_ACKPOLICY, + RF_AT_FUNCID_PKTCONTENT, + RF_AT_FUNCID_RETRYLIMIT, + RF_AT_FUNCID_QUEUE, + RF_AT_FUNCID_BANDWIDTH, + RF_AT_FUNCID_GI, + RF_AT_FUNCID_STBC, + RF_AT_FUNCID_CHNL_FREQ, + RF_AT_FUNCID_RIFS, + RF_AT_FUNCID_TRSW_TYPE, + RF_AT_FUNCID_RF_SX_SHUTDOWN, + RF_AT_FUNCID_PLL_SHUTDOWN, + RF_AT_FUNCID_SLOW_CLK_MODE, + RF_AT_FUNCID_ADC_CLK_MODE, + RF_AT_FUNCID_MEASURE_MODE, + RF_AT_FUNCID_VOLT_COMPEN, + RF_AT_FUNCID_DPD_TX_GAIN, + RF_AT_FUNCID_DPD_MODE, + RF_AT_FUNCID_TSSI_MODE, + RF_AT_FUNCID_TX_GAIN_CODE, + RF_AT_FUNCID_TX_PWR_MODE, + + /* Query command */ + RF_AT_FUNCID_TXED_COUNT = 32, + RF_AT_FUNCID_TXOK_COUNT, + RF_AT_FUNCID_RXOK_COUNT, + RF_AT_FUNCID_RXERROR_COUNT, + RF_AT_FUNCID_RESULT_INFO, + RF_AT_FUNCID_TRX_IQ_RESULT, + RF_AT_FUNCID_TSSI_RESULT, + RF_AT_FUNCID_DPD_RESULT, + RF_AT_FUNCID_RXV_DUMP, + RF_AT_FUNCID_RX_PHY_STATIS, + RF_AT_FUNCID_MEASURE_RESULT, + RF_AT_FUNCID_TEMP_SENSOR, + RF_AT_FUNCID_VOLT_SENSOR, + RF_AT_FUNCID_READ_EFUSE, + RF_AT_FUNCID_RX_RSSI, + RF_AT_FUNCID_FW_INFO, + RF_AT_FUNCID_DRV_INFO, + + /* Set command */ + RF_AT_FUNCID_SET_DPD_RESULT = 64, + RF_AT_FUNCID_SET_CW_MODE, + RF_AT_FUNCID_SET_JAPAN_CH14_FILTER, + RF_AT_FUNCID_WRITE_EFUSE, + RF_AT_FUNCID_SET_MAC_ADDRESS + +} ENUM_RF_AT_FUNCID_T; + +// Command +typedef enum _ENUM_RF_AT_COMMAND_T { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + RF_AT_COMMAND_LO_LEAKAGE, /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_CARRIER_SUPPR, /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_NUM +} ENUM_RF_AT_COMMAND_T; + +// Preamble +typedef enum _ENUM_RF_AT_PREAMBLE_T { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_NUM +} ENUM_RF_AT_PREAMBLE_T; + +// Ack Policy +typedef enum _ENUM_RF_AT_ACK_POLICY_T { + RF_AT_ACK_POLICY_NORMAL = 0, + RF_AT_ACK_POLICY_NOACK, + RF_AT_ACK_POLICY_NOEXPLICTACK, + RF_AT_ACK_POLICY_BLOCKACK, + RF_AT_ACK_POLICY_NUM +} ENUM_RF_AT_ACK_POLICY_T; + +typedef enum _ENUM_RF_AUTOTEST_STATE_T { + RF_AUTOTEST_STATE_STANDBY = 0, + RF_AUTOTEST_STATE_TX, + RF_AUTOTEST_STATE_RX, + RF_AUTOTEST_STATE_RESET, + RF_AUTOTEST_STATE_OUTPUT_POWER, + RF_AUTOTEST_STATE_LOCA_FREQUENCY, + RF_AUTOTEST_STATE_CARRIER_SUPRRESION, + RF_AUTOTEST_STATE_NUM +} ENUM_RF_AUTOTEST_STATE_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS +rftestSetATInfo( + IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, + UINT_32 u4FuncData + ); + +WLAN_STATUS +rftestQueryATInfo( + IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, + UINT_32 u4FuncData, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen + ); + +WLAN_STATUS +rftestSetFrequency( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4FreqInKHz, + IN PUINT_32 pu4SetInfoLen + ); + +#endif /* _RFTEST_H */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h new file mode 100755 index 000000000000..5db05c055bb0 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h @@ -0,0 +1,239 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/typedef.h#1 $ +*/ + +/*! \file typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to the GLUE Layer. +*/ + + + +/* +** $Log: typedef.h $ + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add Ethernet destination address information in packet info for TX + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:41:37 GMT mtk01461 +** Update PACKET_INFO_INIT for TX Path +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:30:17 GMT mtk01461 +** Add parameter in PACKET_INFO_T for HIF Loopback +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:22 GMT mtk01461 +** Fix LINT warning +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:28 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:54 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _TYPEDEF_H +#define _TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* ieee80211.h of linux has duplicated definitions */ +#if defined(WLAN_STATUS_SUCCESS) +#undef WLAN_STATUS_SUCCESS +#endif + +#define WLAN_STATUS_SUCCESS ((WLAN_STATUS) 0x00000000L) +#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((WLAN_STATUS) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((WLAN_STATUS) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((WLAN_STATUS) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((WLAN_STATUS) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((WLAN_STATUS) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((WLAN_STATUS) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((WLAN_STATUS) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((WLAN_STATUS) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((WLAN_STATUS) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((WLAN_STATUS) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((WLAN_STATUS) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((WLAN_STATUS) 0xC0010016L) + +#define WLAN_STATUS_BWCS_UPDATE ((WLAN_STATUS) 0xC0010017L) + +#define WLAN_STATUS_CONNECT_INDICATION ((WLAN_STATUS) 0xC0010018L) + + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/* Type Length */ +#define TL_IPV4 0x0008 +#define TL_IPV6 0xDD86 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for GLUE_INFO structure */ +typedef struct _GLUE_INFO_T GLUE_INFO_T, *P_GLUE_INFO_T; + +/* Type definition for WLAN STATUS */ +typedef UINT_32 WLAN_STATUS, *P_WLAN_STATUS; + +/* Type definition for ADAPTER structure */ +typedef struct _ADAPTER_T ADAPTER_T, *P_ADAPTER_T; + +/* Type definition for MESSAGE HEADER structure */ +typedef struct _MSG_HDR_T MSG_HDR_T, *P_MSG_HDR_T; + +/* Type definition for Pointer to OS Native Packet */ +typedef void *P_NATIVE_PACKET; + +/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception + * for a particular STA. + */ +typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; + +/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to + * the TX Path to reduce the parameters of a function call. + */ +typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; + +/* Following typedef should be removed later, because Glue Layer should not + * be aware of following data type. + */ +typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; + +typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; + +typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; + +/* IST handler definition */ +typedef VOID (*IST_EVENT_FUNCTION)(P_ADAPTER_T); + +/* Type definition for function pointer of timer handler */ +typedef VOID (*PFN_TIMER_CALLBACK)(IN P_GLUE_INFO_T); + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _TYPEDEF_H */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h new file mode 100755 index 000000000000..a3c4d3849a05 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h @@ -0,0 +1,547 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_bow.h#1 $ +*/ + +/*! \file "wlan_bow.h" + \brief This file contains the declairations of 802.11 PAL + command processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_bow.h $ + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 23 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add some BoW error handling. + * + * 05 21 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Protect BoW connection establishment. + * + * 05 17 2011 terry.wu + * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting + * Send deauth while disconnecting BoW link. + * + * 05 06 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix BoW Multiple Physical Link connect/disconnect issue. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW table. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update bowString and channel grant. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW Activity Report structure and bug fix. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose +** +*/ + +#ifndef _WLAN_BOW_H +#define _WLAN_BOW_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "nic/bow.h" +#include "nic/cmd_buf.h" + +#if CFG_ENABLE_BT_OVER_WIFI +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BOWCMD_STATUS_SUCCESS 0 +#define BOWCMD_STATUS_FAILURE 1 +#define BOWCMD_STATUS_UNACCEPTED 2 +#define BOWCMD_STATUS_INVALID 3 +#define BOWCMD_STATUS_TIMEOUT 4 + +#define BOW_WILDCARD_SSID "AMP" +#define BOW_WILDCARD_SSID_LEN 3 +#define BOW_SSID_LEN 21 + + /* 0: query, 1: setup, 2: destroy */ +#define BOW_QUERY_CMD 0 +#define BOW_SETUP_CMD 1 +#define BOW_DESTROY_CMD 2 + +#define BOW_INITIATOR 0 +#define BOW_RESPONDER 1 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +typedef struct _BOW_TABLE_T { + UINT_8 ucAcquireID; + BOOLEAN fgIsValid; + ENUM_BOW_DEVICE_STATE eState; + UINT_8 aucPeerAddress[6]; + //UINT_8 ucRole; + //UINT_8 ucChannelNum; + UINT_16 u2Reserved; +} BOW_TABLE_T, *P_BOW_TABLE_T; + +typedef WLAN_STATUS (*PFN_BOW_CMD_HANDLE)(P_ADAPTER_T, P_AMPC_COMMAND); + +typedef struct _BOW_CMD_T { + UINT_8 uCmdID; + PFN_BOW_CMD_HANDLE pfCmdHandle; +} BOW_CMD_T, *P_BOW_CMD_T; + +typedef struct _BOW_EVENT_ACTIVITY_REPORT_T { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_EVENT_ACTIVITY_REPORT_T, *P_BOW_EVENT_ACTIVITY_REPORT_T; + +/* +ucReason: 0: success + 1: general failure + 2: too much time (> 2/3 second totally) requested for scheduling. + Others: reserved. +*/ + +typedef struct _BOW_EVENT_SYNC_TSF_T { + UINT_64 u4TsfTime; + UINT_32 u4TsfSysTime; + UINT_32 u4ScoTime; + UINT_32 u4ScoSysTime; + } BOW_EVENT_SYNC_TSF_T, *P_BOW_EVENT_SYNC_TSF_T; + +typedef struct _BOW_ACTIVITY_REPORT_BODY_T { + UINT_32 u4StartTime; + UINT_32 u4Duration; + UINT_32 u4Periodicity; + } BOW_ACTIVITY_REPORT_BODY_T, *P_BOW_ACTIVITY_REPORT_BODY_T; + +typedef struct _BOW_ACTIVITY_REPORT_T { + UINT_8 aucPeerAddress[6]; + UINT_8 ucScheduleKnown; + UINT_8 ucNumReports; + BOW_ACTIVITY_REPORT_BODY_T arBowActivityReportBody[MAX_ACTIVITY_REPORT]; + } BOW_ACTIVITY_REPORT_T, *P_BOW_ACTIVITY_REPORT_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, + IN UINT_8 ucSeqNumber + ); + + +/*--------------------------------------------------------------*/ +/* Command Dispatcher */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanbowHandleCommand( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +bowCmdGetMacStatus( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdSetupConnection( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdDestroyConnection( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdSetPTK( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdReadRSSI( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdReadLinkQuality( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdShortRangeMode( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +WLAN_STATUS +bowCmdGetChannelList( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd + ); + +VOID +wlanbowCmdEventSetStatus( + IN P_ADAPTER_T prAdapter, + IN P_AMPC_COMMAND prCmd, + IN UINT_8 ucEventBuf + ); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ +VOID +wlanbowCmdEventSetCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdEventLinkConnected ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdEventLinkDisconnected ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdEventSetSetupConnection ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdEventReadLinkQuality ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdEventReadRssi ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanbowCmdTimeoutHandler ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +VOID +bowStopping( + IN P_ADAPTER_T prAdapter); + +VOID +bowStarting ( + IN P_ADAPTER_T prAdapter + ); + +VOID +bowAssignSsid ( + IN PUINT_8 pucSsid, + IN PUINT_8 pucSsidLen + ); + +BOOLEAN +bowValidateProbeReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ); + +VOID +bowSendBeacon( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ); + +VOID +bowResponderScan( + IN P_ADAPTER_T prAdapter + ); + +VOID +bowResponderScanDone( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +bowResponderCancelScan ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsChannelExtention + ); + +VOID +bowResponderJoin( + IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ); + +VOID +bowFsmRunEventJoinComplete( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +bowIndicationOfMediaStateToHost( + IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, + BOOLEAN fgDelayIndication + ); + +VOID +bowRunEventAAATxFail( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +WLAN_STATUS +bowRunEventAAAComplete( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ); + +WLAN_STATUS +bowRunEventRxDeAuth ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ); + +VOID +bowDisconnectLink ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +BOOLEAN +bowValidateAssocReq( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ); + +BOOLEAN +bowValidateAuth( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PP_STA_RECORD_T pprStaRec, + OUT PUINT_16 pu2StatusCode + ); + +VOID +bowRunEventChGrant ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ); + +VOID +bowRequestCh ( + IN P_ADAPTER_T prAdapter + ); + +VOID +bowReleaseCh ( + IN P_ADAPTER_T prAdapter + ); + +VOID +bowChGrantedTimeout( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ); + +BOOLEAN +bowNotifyAllLinkDisconnected ( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +bowCheckBowTableIfVaild( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6] + ); + +BOOLEAN +bowGetBowTableContent( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBowTableIdx, + OUT P_BOW_TABLE_T prBowTable + ); + +BOOLEAN +bowGetBowTableEntryByPeerAddress( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6], + OUT PUINT_8 pucBowTableIdx + ); + +BOOLEAN +bowGetBowTableFreeEntry( + IN P_ADAPTER_T prAdapter, + OUT PUINT_8 pucBowTableIdx + ); + +ENUM_BOW_DEVICE_STATE +bowGetBowTableState( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6] + ); + +BOOLEAN +bowSetBowTableState( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucPeerAddress[6], + IN ENUM_BOW_DEVICE_STATE eState + ); + + +BOOLEAN +bowSetBowTableContent( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBowTableIdx, + IN P_BOW_TABLE_T prBowTable + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h new file mode 100755 index 000000000000..5141726b1fec --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h @@ -0,0 +1,1042 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_lib.h#1 $ +*/ + +/*! \file "wlan_lib.h" + \brief The declaration of the functions of the wlanAdpater objects + + Detail description. +*/ + + + +/* +** $Log: wlan_lib.h $ + * + * 06 08 2012 eason.tsai + * NULL + * Nvram context covert from 6620 to 6628 for old 6620 meta tool + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * eliminate win32 native data types. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 20 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * change window registry of driver for roaming. + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer when the corresponding BSS is disconnected due to beacon timeout + * remove from scanning result when the BSS is disconnected due to beacon timeout. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 george.huang + * NULL + * . + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * simplify timer usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add extra 64 adjustable parameters for CoEX scenario. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * 2) add 2 kal API for later integration + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * separate wlanProcesQueuePacket() into 2 APIs upon request + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * * * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * 4) nicRxWaitResponse() revised + * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * 4. correct some HAL implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:39:55 GMT mtk02752 +** eliminate unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:58:41 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-19 10:43:06 GMT mtk01461 +** Add wlanReleasePendingOid() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-13 16:38:44 GMT mtk01084 +** add WIFI start function +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-08 16:51:14 GMT mtk01084 +** Update for the image download part +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:57:38 GMT mtk01461 +** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:31:02 GMT mtk01461 +** Add declaration of FW Image download reference code +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:31 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:04 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_LIB_H +#define _WLAN_LIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "CFG_Wifi_File.h" +#include "rlm_domain.h" +#include "wlan_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ + + + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0,2) +#define CSUM_OFFLOAD_EN_ALL BITS(0,6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef WLAN_STATUS (*PFN_OID_HANDLER_FUNC) ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvBuf, + IN UINT_32 u4BufLen, + OUT PUINT_32 pu4OutInfoLen + ); + +typedef enum _ENUM_CSUM_TYPE_T { + CSUM_TYPE_IPV4, + CSUM_TYPE_IPV6, + CSUM_TYPE_TCP, + CSUM_TYPE_UDP, + CSUM_TYPE_NUM +} ENUM_CSUM_TYPE_T, *P_ENUM_CSUM_TYPE_T; + +typedef enum _ENUM_CSUM_RESULT_T { + CSUM_RES_NONE, + CSUM_RES_SUCCESS, + CSUM_RES_FAILED, + CSUM_RES_NUM +} ENUM_CSUM_RESULT_T, *P_ENUM_CSUM_RESULT_T; + +typedef enum _ENUM_PHY_MODE_T { + ENUM_PHY_2G4_CCK, + ENUM_PHY_2G4_OFDM_BPSK, + ENUM_PHY_2G4_OFDM_QPSK, + ENUM_PHY_2G4_OFDM_16QAM, + ENUM_PHY_2G4_OFDM_48M, + ENUM_PHY_2G4_OFDM_54M, + ENUM_PHY_2G4_HT20_BPSK, + ENUM_PHY_2G4_HT20_QPSK, + ENUM_PHY_2G4_HT20_16QAM, + ENUM_PHY_2G4_HT20_MCS5, + ENUM_PHY_2G4_HT20_MCS6, + ENUM_PHY_2G4_HT20_MCS7, + ENUM_PHY_2G4_HT40_BPSK, + ENUM_PHY_2G4_HT40_QPSK, + ENUM_PHY_2G4_HT40_16QAM, + ENUM_PHY_2G4_HT40_MCS5, + ENUM_PHY_2G4_HT40_MCS6, + ENUM_PHY_2G4_HT40_MCS7, + ENUM_PHY_5G_OFDM_BPSK, + ENUM_PHY_5G_OFDM_QPSK, + ENUM_PHY_5G_OFDM_16QAM, + ENUM_PHY_5G_OFDM_48M, + ENUM_PHY_5G_OFDM_54M, + ENUM_PHY_5G_HT20_BPSK, + ENUM_PHY_5G_HT20_QPSK, + ENUM_PHY_5G_HT20_16QAM, + ENUM_PHY_5G_HT20_MCS5, + ENUM_PHY_5G_HT20_MCS6, + ENUM_PHY_5G_HT20_MCS7, + ENUM_PHY_5G_HT40_BPSK, + ENUM_PHY_5G_HT40_QPSK, + ENUM_PHY_5G_HT40_16QAM, + ENUM_PHY_5G_HT40_MCS5, + ENUM_PHY_5G_HT40_MCS6, + ENUM_PHY_5G_HT40_MCS7, + ENUM_PHY_MODE_NUM +} ENUM_PHY_MODE_T, *P_ENUM_PHY_MODE_T; + +typedef enum _ENUM_POWER_SAVE_POLL_MODE_T { + ENUM_POWER_SAVE_POLL_DISABLE, + ENUM_POWER_SAVE_POLL_LEGACY_NULL, + ENUM_POWER_SAVE_POLL_QOS_NULL, + ENUM_POWER_SAVE_POLL_NUM +} ENUM_POWER_SAVE_POLL_MODE_T, *P_ENUM_POWER_SAVE_POLL_MODE_T; + +typedef enum _ENUM_AC_TYPE_T { + ENUM_AC_TYPE_AC0, + ENUM_AC_TYPE_AC1, + ENUM_AC_TYPE_AC2, + ENUM_AC_TYPE_AC3, + ENUM_AC_TYPE_AC4, + ENUM_AC_TYPE_AC5, + ENUM_AC_TYPE_AC6, + ENUM_AC_TYPE_BMC, + ENUM_AC_TYPE_NUM +} ENUM_AC_TYPE_T, *P_ENUM_AC_TYPE_T; + +typedef enum _ENUM_ADV_AC_TYPE_T { + ENUM_ADV_AC_TYPE_RX_NSW, + ENUM_ADV_AC_TYPE_RX_PTA, + ENUM_ADV_AC_TYPE_RX_SP, + ENUM_ADV_AC_TYPE_TX_PTA, + ENUM_ADV_AC_TYPE_TX_RSP, + ENUM_ADV_AC_TYPE_NUM +} ENUM_ADV_AC_TYPE_T, *P_ENUM_ADV_AC_TYPE_T; + +typedef enum _ENUM_REG_CH_MAP_T { + REG_CH_MAP_COUNTRY_CODE, + REG_CH_MAP_TBL_IDX, + REG_CH_MAP_CUSTOMIZED, + REG_CH_MAP_NUM +} ENUM_REG_CH_MAP_T, *P_ENUM_REG_CH_MAP_T; + +typedef struct _SET_TXPWR_CTRL_T{ + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0*/ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0*/ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence + in the same channel + 0: Highest power has priority + 1: Lowest power has priority */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm*/ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; + +/* For storing driver initialization value from glue layer */ +typedef struct _REG_INFO_T { + UINT_32 u4SdBlockSize; /* SDIO block size */ + UINT_32 u4SdBusWidth; /* SDIO bus width. 1 or 4 */ + UINT_32 u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ + UINT_32 u4StartAddress; /* Starting address of Wi-Fi Firmware */ + UINT_32 u4LoadAddress; /* Load address of Wi-Fi Firmware */ + UINT_16 aucFwImgFilename[65]; /* Firmware filename */ + UINT_16 aucFwImgFilenameE6[65]; /* Firmware filename for E6 */ + UINT_32 u4StartFreq; /* Start Frequency for Ad-Hoc network : in unit of KHz */ + UINT_32 u4AdhocMode; /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ + UINT_32 u4RddStartFreq; + UINT_32 u4RddStopFreq; + UINT_32 u4RddTestMode; + UINT_32 u4RddShutFreq; + UINT_32 u4RddDfs; + INT_32 i4HighRssiThreshold; + INT_32 i4MediumRssiThreshold; + INT_32 i4LowRssiThreshold; + INT_32 au4TxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4RxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; + UINT_32 u4FastPSPoll; + UINT_32 u4PTA; /* 0: disable, 1: enable */ + UINT_32 u4TXLimit; /* 0: disable, 1: enable */ + UINT_32 u4SilenceWindow; /* range: 100 - 625, unit: us */ + UINT_32 u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ + UINT_32 u4PowerMode; + UINT_32 fgEnArpFilter; + UINT_32 u4PsCurrentMeasureEn; + UINT_32 u4UapsdAcBmp; + UINT_32 u4MaxSpLen; + UINT_32 fgDisOnlineScan; /* 0: enable online scan, non-zero: disable online scan*/ + UINT_32 fgDisBcnLostDetection; /* 0: enable online scan, non-zero: disable online scan*/ + UINT_32 u4FixedRate; /* 0: automatic, non-zero: fixed rate */ + UINT_32 u4ArSysParam0; + UINT_32 u4ArSysParam1; + UINT_32 u4ArSysParam2; + UINT_32 u4ArSysParam3; + UINT_32 fgDisRoaming; /* 0:enable roaming 1:disable */ + + // NVRAM - MP Data -START- + UINT_8 aucMacAddr[6]; + UINT_16 au2CountryCode[4]; /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ + TX_PWR_PARAM_T rTxPwr; + UINT_8 aucEFUSE[144]; + UINT_8 ucTxPwrValid; + UINT_8 ucSupport5GBand; + UINT_8 fg2G4BandEdgePwrUsed; + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + ENUM_REG_CH_MAP_T eRegChannelListMap; + UINT_8 ucRegChannelListIndex; + DOMAIN_INFO_ENTRY rDomainInfo; + // NVRAM - MP Data -END- + + // NVRAM - Functional Data -START- + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + // NVRAM - Functional Data -END- + +} REG_INFO_T, *P_REG_INFO_T; + +/* for divided firmware loading */ +typedef struct _FWDL_SECTION_INFO_T +{ + UINT_32 u4Offset; + UINT_32 u4Reserved; + UINT_32 u4Length; + UINT_32 u4DestAddr; +} FWDL_SECTION_INFO_T, *P_FWDL_SECTION_INFO_T; + +typedef struct _FIRMWARE_DIVIDED_DOWNLOAD_T +{ + UINT_32 u4Signature; + UINT_32 u4CRC; /* CRC calculated without first 8 bytes included */ + UINT_32 u4NumOfEntries; + UINT_32 u4Reserved; + FWDL_SECTION_INFO_T arSection[]; +} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; + +typedef struct _PARAM_MCR_RW_STRUC_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_MCR_RW_STRUC_T, *P_PARAM_MCR_RW_STRUC_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((UINT_32)(UINT_8)(ch0) | ((UINT_32)(UINT_8)(ch1) << 8) | \ + ((UINT_32)(UINT_8)(ch2) << 16) | ((UINT_32)(UINT_8)(ch3) << 24 )) + +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_ADAPTER_T +wlanAdapterCreate ( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +wlanAdapterDestroy ( + IN P_ADAPTER_T prAdapter + ); + +VOID +wlanCardEjected( + IN P_ADAPTER_T prAdapter + ); + +VOID +wlanIST ( + IN P_ADAPTER_T prAdapter + ); + +BOOL +wlanISR ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgGlobalIntrCtrl + ); + +WLAN_STATUS +wlanProcessCommandQueue ( + IN P_ADAPTER_T prAdapter, + IN P_QUE_T prCmdQue + ); + +WLAN_STATUS +wlanSendCommand ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +VOID +wlanReleaseCommand ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +VOID +wlanReleasePendingOid ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Data + ); + +VOID +wlanReleasePendingCMDbyNetwork( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ); + +VOID +wlanReturnPacket ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvPacket + ); + +WLAN_STATUS +wlanQueryInformation ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidQryHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + OUT PUINT_32 pu4QryInfoLen + ); + +WLAN_STATUS +wlanSetInformation ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidSetHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanAdapterStart ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, + IN PVOID pvFwImageMapFile, + IN UINT_32 u4FwImageFileLength + ); + +WLAN_STATUS +wlanAdapterStop ( + IN P_ADAPTER_T prAdapter + ); + +#if CFG_SUPPORT_WAPI +BOOLEAN +wlanQueryWapiMode( + IN P_ADAPTER_T prAdapter + ); +#endif + +VOID +wlanReturnRxPacket ( + IN PVOID pvAdapter, + IN PVOID pvPacket + ); + +VOID +wlanRxSetBroadcast ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnableBroadcast + ); + +BOOLEAN +wlanIsHandlerNeedHwAccess ( + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN BOOLEAN fgSetInfo + ); + +VOID +wlanSetPromiscuousMode ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnablePromiscuousMode + ); + +#if CFG_ENABLE_FW_DOWNLOAD + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +WLAN_STATUS +wlanImageSectionDownloadAggregated ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, + IN UINT_32 u4ImgSecSize, + IN PUINT_8 pucImgSecBuf + ); + #endif + +WLAN_STATUS +wlanImageSectionDownload ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, + IN UINT_32 u4ImgSecSize, + IN PUINT_8 pucImgSecBuf + ); + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +WLAN_STATUS +wlanImageQueryStatus( + IN P_ADAPTER_T prAdapter + ); +#else +WLAN_STATUS +wlanImageSectionDownloadStatus ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCmdSeqNum + ); +#endif + +WLAN_STATUS +wlanConfigWifiFunc ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnable, + IN UINT_32 u4StartAddress + ); + +UINT_32 wlanCRC32( + PUINT_8 buf, + UINT_32 len + ); + +#endif + +WLAN_STATUS +wlanSendNicPowerCtrlCmd ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPowerMode + ); + +BOOLEAN +wlanIsHandlerAllowedInRFTest ( + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN BOOLEAN fgSetInfo + ); + +WLAN_STATUS +wlanProcessQueuedSwRfb ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfbListHead + ); + +WLAN_STATUS +wlanProcessQueuedMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ); + +BOOLEAN +wlanoidTimeoutCheck ( + IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler + ); + +VOID +wlanoidClearTimeoutCheck ( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +wlanUpdateNetworkAddress ( + IN P_ADAPTER_T prAdapter + ); + +BOOLEAN +wlanQueryTestMode( + IN P_ADAPTER_T prAdapter + ); + +/* Security Frame Handling */ +BOOLEAN +wlanProcessSecurityFrame( + IN P_ADAPTER_T prAdapter, + IN P_NATIVE_PACKET prPacket + ); + +VOID +wlanSecurityFrameTxDone( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); + +VOID +wlanSecurityFrameTxTimeout( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID +wlanClearScanningResult( + IN P_ADAPTER_T prAdapter + ); + +VOID +wlanClearBssInScanningResult( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 arBSSID + ); + +#if CFG_TEST_WIFI_DIRECT_GO +VOID +wlanEnableP2pFunction( + IN P_ADAPTER_T prAdapter + ); + +VOID +wlanEnableATGO( + IN P_ADAPTER_T prAdapter + ); +#endif + + +/*----------------------------------------------------------------------------*/ +/* Address Retreive by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryPermanentAddress( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryNicCapability( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* PD MCR Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryPdMcr( + IN P_ADAPTER_T prAdapter, + IN P_PARAM_MCR_RW_STRUC_T prMcrRdInfo + ); +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanLoadManufactureData ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ); + + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanResetMediaStreamMode( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanTimerTimeoutCheck( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanProcessMboxMessage( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanEnqueueTxPacket ( + IN P_ADAPTER_T prAdapter, + IN P_NATIVE_PACKET prNativePacket + ); + +WLAN_STATUS +wlanFlushTxPendingPackets( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +wlanTxPendingPackets ( + IN P_ADAPTER_T prAdapter, + IN OUT PBOOLEAN pfgHwAccess + ); + + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAcquirePowerControl( + IN P_ADAPTER_T prAdapter + ); + +WLAN_STATUS +wlanReleasePowerControl( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +UINT_32 +wlanGetTxPendingFrameCount ( + IN P_ADAPTER_T prAdapter + ); + + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T +wlanGetAcpiState ( + IN P_ADAPTER_T prAdapter + ); + +VOID +wlanSetAcpiState ( + IN P_ADAPTER_T prAdapter, + IN ENUM_ACPI_STATE_T ePowerState + ); + +#if CFG_SUPPORT_OSC_SETTING && defined(MT5931) +WLAN_STATUS +wlanSetMcuOscStableTime ( + IN P_ADAPTER_T prAdapter, + IN UINT_16 u2OscStableTime + ); +#endif + +VOID +wlanDefTxPowerCfg ( + IN P_ADAPTER_T prAdapter + ); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +UINT_8 +wlanGetEcoVersion( + IN P_ADAPTER_T prAdapter + ); + +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +UINT_8 +wlanGetChannelNumberByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +/*----------------------------------------------------------------------------*/ +/* get BSS Descriptor information */ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +wlanGetTargetBssDescByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanCheckSystemConfiguration ( + IN P_ADAPTER_T prAdapter + ); + + +#endif /* _WLAN_LIB_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h new file mode 100755 index 000000000000..ea28d126b9f1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h @@ -0,0 +1,2061 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_oid.h#2 $ +*/ + +/*! \file "wlan_oid.h" + \brief This file contains the declairation file of the WLAN OID processing routines + of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_oid.h $ + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. + * + + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 04 22 2010 cp.wu + * [WPD00003830]add OID_802_11_PRIVACY_FILTER support + * enable RX filter OID + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * OID_802_11_RSSI, + * * * * OID_802_11_RSSI_TRIGGER, + * * * * OID_802_11_STATISTICS, + * * * * OID_802_11_DISASSOCIATE, + * * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-08 11:38:11 GMT mtk02752 +** add declares for RF test related APIs +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-24 22:41:53 GMT mtk02752 +** remove u4SysTime, MSDN 10-second will be implemented in FW side +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 20:30:13 GMT mtk02752 +** add u4SysTime field in PARAM_BSSID_EX_T +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-12 19:48:35 GMT mtk02752 +** allow upper layer to set a packet filter with PROMISCUOUS mode +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:12 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_OID_H +#define _WLAN_OID_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define PARAM_MAX_LEN_SSID 32 + +#define PARAM_MAC_ADDR_LEN 6 + +#define ETHERNET_HEADER_SZ 14 +#define ETHERNET_MIN_PKT_SZ 60 +#define ETHERNET_MAX_PKT_SZ 1514 + +#define PARAM_MAX_LEN_RATES 8 +#define PARAM_MAX_LEN_RATES_EX 16 + +#define PARAM_AUTH_REQUEST_REAUTH 0x01 +#define PARAM_AUTH_REQUEST_KEYUPDATE 0x02 +#define PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E + +#define PARAM_EEPROM_READ_METHOD_READ 1 +#define PARAM_EEPROM_READ_METHOD_GETSIZE 0 + +#define PARAM_WHQL_RSSI_MAX_DBM (-10) +#define PARAM_WHQL_RSSI_MIN_DBM (-200) + +#define PARAM_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define PARAM_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define PARAM_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +#define PARAM_WAKE_UP_MAGIC_PACKET 0x00000001 +#define PARAM_WAKE_UP_PATTERN_MATCH 0x00000002 +#define PARAM_WAKE_UP_LINK_CHANGE 0x00000004 + + +/* Packet filter bit definitioin (UINT_32 bit-wise definition) */ +#define PARAM_PACKET_FILTER_DIRECTED 0x00000001 +#define PARAM_PACKET_FILTER_MULTICAST 0x00000002 +#define PARAM_PACKET_FILTER_ALL_MULTICAST 0x00000004 +#define PARAM_PACKET_FILTER_BROADCAST 0x00000008 +#define PARAM_PACKET_FILTER_PROMISCUOUS 0x00000020 +#define PARAM_PACKET_FILTER_ALL_LOCAL 0x00000080 +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#define PARAM_PACKET_FILTER_P2P_MASK 0xC0000000 +#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 +#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 +#endif + +#if CFG_SLT_SUPPORT +#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ + PARAM_PACKET_FILTER_MULTICAST | \ + PARAM_PACKET_FILTER_BROADCAST | \ + PARAM_PACKET_FILTER_ALL_MULTICAST) +#else +#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ + PARAM_PACKET_FILTER_MULTICAST | \ + PARAM_PACKET_FILTER_BROADCAST) +#endif + +#define PARAM_MEM_DUMP_MAX_SIZE 2048 + +#define BT_PROFILE_PARAM_LEN 8 +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration which match to NDIS5.1 */ +/*----------------------------------------------------------------------------*/ +/* NDIS_802_11_AUTHENTICATION_MODE */ +typedef enum _ENUM_PARAM_AUTH_MODE_T +{ + AUTH_MODE_OPEN, /*!< Open system */ + AUTH_MODE_SHARED, /*!< Shared key */ + AUTH_MODE_AUTO_SWITCH, /*!< Either open system or shared key */ + AUTH_MODE_WPA, + AUTH_MODE_WPA_PSK, + AUTH_MODE_WPA_NONE, /*!< For Ad hoc */ + AUTH_MODE_WPA2, + AUTH_MODE_WPA2_PSK, + AUTH_MODE_NUM /*!< Upper bound, not real case */ +} ENUM_PARAM_AUTH_MODE_T, *P_ENUM_PARAM_AUTH_MODE_T; + +/* NDIS_802_11_ENCRYPTION_STATUS *//* Encryption types */ +typedef enum _ENUM_WEP_STATUS_T +{ + ENUM_WEP_ENABLED, + ENUM_ENCRYPTION1_ENABLED = ENUM_WEP_ENABLED, + ENUM_WEP_DISABLED, + ENUM_ENCRYPTION_DISABLED = ENUM_WEP_DISABLED, + ENUM_WEP_KEY_ABSENT, + ENUM_ENCRYPTION1_KEY_ABSENT = ENUM_WEP_KEY_ABSENT, + ENUM_WEP_NOT_SUPPORTED, + ENUM_ENCRYPTION_NOT_SUPPORTED = ENUM_WEP_NOT_SUPPORTED, + ENUM_ENCRYPTION2_ENABLED, + ENUM_ENCRYPTION2_KEY_ABSENT, + ENUM_ENCRYPTION3_ENABLED, + ENUM_ENCRYPTION3_KEY_ABSENT +} ENUM_PARAM_ENCRYPTION_STATUS_T, *P_ENUM_PARAM_ENCRYPTION_STATUS_T; + + + +typedef UINT_8 PARAM_MAC_ADDRESS[PARAM_MAC_ADDR_LEN]; + +typedef UINT_32 PARAM_KEY_INDEX; +typedef UINT_64 PARAM_KEY_RSC; +typedef INT_32 PARAM_RSSI; + +typedef UINT_32 PARAM_FRAGMENTATION_THRESHOLD; +typedef UINT_32 PARAM_RTS_THRESHOLD; + +typedef UINT_8 PARAM_RATES[PARAM_MAX_LEN_RATES]; +typedef UINT_8 PARAM_RATES_EX[PARAM_MAX_LEN_RATES_EX]; + +typedef enum _ENUM_PARAM_PHY_TYPE_T { + PHY_TYPE_802_11ABG = 0, /*!< Can associated with 802.11abg AP, Scan dual band. */ + PHY_TYPE_802_11BG, /*!< Can associated with 802_11bg AP, Scan single band and not report 802_11a BSSs. */ + PHY_TYPE_802_11G, /*!< Can associated with 802_11g only AP, Scan single band and not report 802_11ab BSSs. */ + PHY_TYPE_802_11A, /*!< Can associated with 802_11a only AP, Scan single band and not report 802_11bg BSSs. */ + PHY_TYPE_802_11B, /*!< Can associated with 802_11b only AP, Scan single band and not report 802_11ag BSSs. */ + PHY_TYPE_NUM // 5 +} ENUM_PARAM_PHY_TYPE_T, *P_ENUM_PARAM_PHY_TYPE_T; + +typedef enum _ENUM_PARAM_OP_MODE_T { + NET_TYPE_IBSS = 0, /*!< Try to merge/establish an AdHoc, do periodic SCAN for merging. */ + NET_TYPE_INFRA, /*!< Try to join an Infrastructure, do periodic SCAN for joining. */ + NET_TYPE_AUTO_SWITCH, /*!< Try to join an Infrastructure, if fail then try to merge or + establish an AdHoc, do periodic SCAN for joining or merging. */ + NET_TYPE_DEDICATED_IBSS, /*!< Try to merge an AdHoc first, if fail then establish AdHoc permanently, no more SCAN. */ + NET_TYPE_NUM // 4 +} ENUM_PARAM_OP_MODE_T, *P_ENUM_PARAM_OP_MODE_T; + +typedef struct _PARAM_SSID_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; +} PARAM_SSID_T, *P_PARAM_SSID_T; + +/* This is enum defined for user to select an AdHoc Mode */ +typedef enum _ENUM_PARAM_AD_HOC_MODE_T { + AD_HOC_MODE_11B = 0, /*!< Create 11b IBSS if we support 802.11abg/802.11bg. */ + AD_HOC_MODE_MIXED_11BG, /*!< Create 11bg mixed IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11G, /*!< Create 11g only IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11A, /*!< Create 11a only IBSS if we support 802.11abg. */ + AD_HOC_MODE_NUM // 4 +} ENUM_PARAM_AD_HOC_MODE_T, *P_ENUM_PARAM_AD_HOC_MODE_T; + + +typedef enum _ENUM_PARAM_MEDIA_STATE_T { + PARAM_MEDIA_STATE_CONNECTED, + PARAM_MEDIA_STATE_DISCONNECTED, + PARAM_MEDIA_STATE_TO_BE_INDICATED // for following MSDN re-association behavior +} ENUM_PARAM_MEDIA_STATE_T, *P_ENUM_PARAM_MEDIA_STATE_T; + + +typedef enum _ENUM_PARAM_NETWORK_TYPE_T { + PARAM_NETWORK_TYPE_FH, + PARAM_NETWORK_TYPE_DS, + PARAM_NETWORK_TYPE_OFDM5, + PARAM_NETWORK_TYPE_OFDM24, + PARAM_NETWORK_TYPE_AUTOMODE, + PARAM_NETWORK_TYPE_NUM /*!< Upper bound, not real case */ +} ENUM_PARAM_NETWORK_TYPE_T, *P_ENUM_PARAM_NETWORK_TYPE_T; + + +typedef struct _PARAM_NETWORK_TYPE_LIST { + UINT_32 NumberOfItems; /*!< At least 1 */ + ENUM_PARAM_NETWORK_TYPE_T eNetworkType [1]; +} PARAM_NETWORK_TYPE_LIST, *PPARAM_NETWORK_TYPE_LIST; + +typedef enum _ENUM_PARAM_PRIVACY_FILTER_T +{ + PRIVACY_FILTER_ACCEPT_ALL, + PRIVACY_FILTER_8021xWEP, + PRIVACY_FILTER_NUM +} ENUM_PARAM_PRIVACY_FILTER_T, *P_ENUM_PARAM_PRIVACY_FILTER_T; + +typedef enum _ENUM_RELOAD_DEFAULTS +{ + ENUM_RELOAD_WEP_KEYS +} PARAM_RELOAD_DEFAULTS, *P_PARAM_RELOAD_DEFAULTS; + +typedef struct _PARAM_PM_PACKET_PATTERN +{ + UINT_32 Priority; // Importance of the given pattern. + UINT_32 Reserved; // Context information for transports. + UINT_32 MaskSize; // Size in bytes of the pattern mask. + UINT_32 PatternOffset; // Offset from beginning of this + // structure to the pattern bytes. + UINT_32 PatternSize; // Size in bytes of the pattern. + UINT_32 PatternFlags; // Flags (TBD). +} PARAM_PM_PACKET_PATTERN, *P_PARAM_PM_PACKET_PATTERN; + +/*--------------------------------------------------------------*/ +/*! \brief Struct definition to indicate specific event. */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_STATUS_TYPE_T +{ + ENUM_STATUS_TYPE_AUTHENTICATION, + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE, + ENUM_STATUS_TYPE_CANDIDATE_LIST, + ENUM_STATUS_TYPE_NUM /*!< Upper bound, not real case */ +} ENUM_STATUS_TYPE_T, *P_ENUM_STATUS_TYPE_T; + + +typedef struct _PARAM_802_11_CONFIG_FH_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4HopPattern; /*!< Defined as 802.11 */ + UINT_32 u4HopSet; /*!< to one if non-802.11 */ + UINT_32 u4DwellTime; /*!< In unit of Kusec */ +} PARAM_802_11_CONFIG_FH_T, *P_PARAM_802_11_CONFIG_FH_T; + +typedef struct _PARAM_802_11_CONFIG_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4BeaconPeriod; /*!< In unit of Kusec */ + UINT_32 u4ATIMWindow; /*!< In unit of Kusec */ + UINT_32 u4DSConfig; /*!< Channel frequency in unit of kHz */ + PARAM_802_11_CONFIG_FH_T rFHConfig; +} PARAM_802_11_CONFIG_T, *P_PARAM_802_11_CONFIG_T; + +typedef struct _PARAM_STATUS_INDICATION_T +{ + ENUM_STATUS_TYPE_T eStatusType; +} PARAM_STATUS_INDICATION_T, *P_PARAM_STATUS_INDICATION_T; + +typedef struct _PARAM_AUTH_REQUEST_T +{ + UINT_32 u4Length; /*!< Length of this struct */ + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4Flags; /*!< Definitions are as follows */ +} PARAM_AUTH_REQUEST_T, *P_PARAM_AUTH_REQUEST_T; + +typedef struct _PARAM_AUTH_EVENT_T +{ + PARAM_STATUS_INDICATION_T rStatus; + PARAM_AUTH_REQUEST_T arRequest[1]; +} PARAM_AUTH_EVENT_T, *P_PARAM_AUTH_EVENT_T; + +/*! \brief Capabilities, privacy, rssi and IEs of each BSSID */ +typedef struct _PARAM_BSSID_EX_T { + UINT_32 u4Length; /*!< Length of structure */ + PARAM_MAC_ADDRESS arMacAddress; /*!< BSSID */ + UINT_8 Reserved[2]; + PARAM_SSID_T rSsid; /*!< SSID */ + UINT_32 u4Privacy; /*!< Need WEP encryption */ + PARAM_RSSI rRssi; /*!< in dBm */ + ENUM_PARAM_NETWORK_TYPE_T eNetworkTypeInUse; + PARAM_802_11_CONFIG_T rConfiguration; + ENUM_PARAM_OP_MODE_T eOpMode; + PARAM_RATES_EX rSupportedRates; + UINT_32 u4IELength; + UINT_8 aucIEs[1]; +} PARAM_BSSID_EX_T, *P_PARAM_BSSID_EX_T; + +typedef struct _PARAM_BSSID_LIST_EX { + UINT_32 u4NumberOfItems; /*!< at least 1 */ + PARAM_BSSID_EX_T arBssid[1]; +} PARAM_BSSID_LIST_EX_T, *P_PARAM_BSSID_LIST_EX_T; + + +typedef struct _PARAM_WEP_T +{ + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< 0: pairwise key, others group keys */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} PARAM_WEP_T, *P_PARAM_WEP_T; + +/*! \brief Key mapping of BSSID */ +typedef struct _PARAM_KEY_T +{ + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ + PARAM_KEY_RSC rKeyRSC; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} PARAM_KEY_T, *P_PARAM_KEY_T; + +typedef struct _PARAM_REMOVE_KEY_T +{ + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ +} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; + +#if CFG_SUPPORT_WAPI +typedef enum _ENUM_KEY_TYPE { + ENUM_WPI_PAIRWISE_KEY = 0, + ENUM_WPI_GROUP_KEY +} ENUM_KEY_TYPE; + +typedef enum _ENUM_WPI_PROTECT_TYPE +{ + ENUM_WPI_NONE, + ENUM_WPI_RX, + ENUM_WPI_TX, + ENUM_WPI_RX_TX +} ENUM_WPI_PROTECT_TYPE; + +typedef struct _PARAM_WPI_KEY_T { + ENUM_KEY_TYPE eKeyType; + ENUM_WPI_PROTECT_TYPE eDirection; + UINT_8 ucKeyID; + UINT_8 aucRsv[3]; + UINT_8 aucAddrIndex[12]; + UINT_32 u4LenWPIEK; + UINT_8 aucWPIEK[256]; + UINT_32 u4LenWPICK; + UINT_8 aucWPICK[256]; + UINT_8 aucPN[16]; +} PARAM_WPI_KEY_T, *P_PARAM_WPI_KEY_T; +#endif + + +typedef enum _PARAM_POWER_MODE +{ + Param_PowerModeCAM, + Param_PowerModeMAX_PSP, + Param_PowerModeFast_PSP, + Param_PowerModeMax /* Upper bound, not real case */ +} PARAM_POWER_MODE, *PPARAM_POWER_MODE; + +typedef enum _PARAM_DEVICE_POWER_STATE +{ + ParamDeviceStateUnspecified = 0, + ParamDeviceStateD0, + ParamDeviceStateD1, + ParamDeviceStateD2, + ParamDeviceStateD3, + ParamDeviceStateMaximum +} PARAM_DEVICE_POWER_STATE, *PPARAM_DEVICE_POWER_STATE; + +#if CFG_SUPPORT_802_11D + +/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ +typedef enum _PARAM_MULTI_DOMAIN_CAPABILITY { + ParamMultiDomainCapDisabled, + ParamMultiDomainCapEnabled +} PARAM_MULTI_DOMAIN_CAPABILITY, *P_PARAM_MULTI_DOMAIN_CAPABILITY; +#endif + +typedef struct _COUNTRY_STRING_ENTRY { + UINT_8 aucCountryCode[2]; + UINT_8 aucEnvironmentCode[2]; +} COUNTRY_STRING_ENTRY, *P_COUNTRY_STRING_ENTRY; + +/* Power management related definition and enumerations */ +#define UAPSD_NONE 0 +#define UAPSD_AC0 (BIT(0) | BIT(4)) +#define UAPSD_AC1 (BIT(1) | BIT(5)) +#define UAPSD_AC2 (BIT(2) | BIT(6)) +#define UAPSD_AC3 (BIT(3) | BIT(7)) +#define UAPSD_ALL (UAPSD_AC0 | UAPSD_AC1 | UAPSD_AC2 | UAPSD_AC3) + +typedef enum _ENUM_POWER_SAVE_PROFILE_T +{ + ENUM_PSP_CONTINUOUS_ACTIVE = 0, + ENUM_PSP_CONTINUOUS_POWER_SAVE, + ENUM_PSP_FAST_SWITCH, + ENUM_PSP_NUM +} ENUM_POWER_SAVE_PROFILE_T, *PENUM_POWER_SAVE_PROFILE_T; + + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query testing type. */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_802_11_TEST_T +{ + UINT_32 u4Length; + UINT_32 u4Type; + union + { + PARAM_AUTH_EVENT_T AuthenticationEvent; + PARAM_RSSI RssiTrigger; + } u; +} PARAM_802_11_TEST_T, *P_PARAM_802_11_TEST_T; + + + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query authentication and encryption capability. */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_AUTH_ENCRYPTION_T +{ + ENUM_PARAM_AUTH_MODE_T eAuthModeSupported; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncryptStatusSupported; +} PARAM_AUTH_ENCRYPTION_T, *P_PARAM_AUTH_ENCRYPTION_T; + +typedef struct _PARAM_CAPABILITY_T +{ + UINT_32 u4Length; + UINT_32 u4Version; + UINT_32 u4NoOfPMKIDs; + UINT_32 u4NoOfAuthEncryptPairsSupported; + PARAM_AUTH_ENCRYPTION_T arAuthenticationEncryptionSupported[1]; +} PARAM_CAPABILITY_T, *P_PARAM_CAPABILITY_T; + +typedef UINT_8 PARAM_PMKID_VALUE[16]; + +typedef struct _PARAM_BSSID_INFO_T +{ + PARAM_MAC_ADDRESS arBSSID; + PARAM_PMKID_VALUE arPMKID; +} PARAM_BSSID_INFO_T, *P_PARAM_BSSID_INFO_T; + +typedef struct _PARAM_PMKID_T +{ + UINT_32 u4Length; + UINT_32 u4BSSIDInfoCount; + PARAM_BSSID_INFO_T arBSSIDInfo[1]; +} PARAM_PMKID_T, *P_PARAM_PMKID_T; + +/*! \brief PMKID candidate lists. */ +typedef struct _PARAM_PMKID_CANDIDATE_T { + PARAM_MAC_ADDRESS arBSSID; + UINT_32 u4Flags; +} PARAM_PMKID_CANDIDATE_T, *P_PARAM_PMKID_CANDIDATE_T; + +//#ifdef LINUX +typedef struct _PARAM_PMKID_CANDIDATE_LIST_T +{ + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} PARAM_PMKID_CANDIDATE_LIST_T, *P_PARAM_PMKID_CANDIDATE_LIST_T; +//#endif + +typedef struct _PARAM_CUSTOM_MCR_RW_STRUC_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_CUSTOM_MCR_RW_STRUC_T, *P_PARAM_CUSTOM_MCR_RW_STRUC_T; + +typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUC_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} PARAM_CUSTOM_MEM_DUMP_STRUC_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUC_T; + + +typedef struct _PARAM_CUSTOM_SW_CTRL_STRUC_T { + UINT_32 u4Id; + UINT_32 u4Data; +} PARAM_CUSTOM_SW_CTRL_STRUC_T, *P_PARAM_CUSTOM_SW_CTRL_STRUC_T; + + +typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUC_T { + UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0*/ + UINT_8 ucEepromIndex; + UINT_8 reserved; + UINT_16 u2EepromData; +} PARAM_CUSTOM_EEPROM_RW_STRUC_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUC_T, + PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUC_T { + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + UINT_8 reserved; +} PARAM_CUSTOM_WMM_PS_TEST_STRUC_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUC_T; + +typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUC_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} PARAM_CUSTOM_NOA_PARAM_STRUC_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUC_T; + +typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUC_T { + UINT_32 u4CTwindowMs; +} PARAM_CUSTOM_OPPPS_PARAM_STRUC_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T; + +typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUC_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} PARAM_CUSTOM_UAPSD_PARAM_STRUC_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T; + +typedef struct _PARAM_CUSTOM_P2P_SET_STRUC_T { + UINT_32 u4Enable; + UINT_32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUC_T, *P_PARAM_CUSTOM_P2P_SET_STRUC_T; + +typedef enum _ENUM_CFG_SRC_TYPE_T { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; + +typedef enum _ENUM_EEPROM_TYPE_T { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; + +typedef struct _PARAM_QOS_TSINFO { + UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ + UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ + UINT_8 ucDirection; /* direction */ + UINT_8 ucAccessPolicy; /* access policy */ + UINT_8 ucAggregation; /* aggregation */ + UINT_8 ucApsd; /* APSD */ + UINT_8 ucuserPriority; /* user priority */ + UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ + UINT_8 ucSchedule; /* Schedule */ +} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; + +typedef struct _PARAM_QOS_TSPEC { + PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ + UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ + UINT_32 u4MinSvcIntv; /* minimum service interval */ + UINT_32 u4MaxSvcIntv; /* maximum service interval */ + UINT_32 u4InactIntv; /* inactivity interval */ + UINT_32 u4SpsIntv; /* suspension interval */ + UINT_32 u4SvcStartTime; /* service start time */ + UINT_32 u4MinDataRate; /* minimum Data rate */ + UINT_32 u4MeanDataRate; /* mean data rate */ + UINT_32 u4PeakDataRate; /* peak data rate */ + UINT_32 u4MaxBurstSize; /* maximum burst size */ + UINT_32 u4DelayBound; /* delay bound */ + UINT_32 u4MinPHYRate; /* minimum PHY rate */ + UINT_16 u2Sba; /* surplus bandwidth allowance */ + UINT_16 u2MediumTime; /* medium time */ +} PARAM_QOS_TSPEC, *P_PARAM_QOS_TSPEC; + +typedef struct _PARAM_QOS_ADDTS_REQ_INFO { + PARAM_QOS_TSPEC rTspec; +} PARAM_QOS_ADDTS_REQ_INFO, *P_PARAM_QOS_ADDTS_REQ_INFO; + +typedef struct _PARAM_VOIP_CONFIG { + UINT_32 u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +} PARAM_VOIP_CONFIG, *P_PARAM_VOIP_CONFIG; + +/*802.11 Statistics Struct*/ +typedef struct _PARAM_802_11_STATISTICS_STRUCT_T { + UINT_32 u4Length; // Length of structure + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; + LARGE_INTEGER rTKIPLocalMICFailures; + LARGE_INTEGER rTKIPICVErrors; + LARGE_INTEGER rTKIPCounterMeasuresInvoked; + LARGE_INTEGER rTKIPReplays; + LARGE_INTEGER rCCMPFormatErrors; + LARGE_INTEGER rCCMPReplays; + LARGE_INTEGER rCCMPDecryptErrors; + LARGE_INTEGER rFourWayHandshakeFailures; + LARGE_INTEGER rWEPUndecryptableCount; + LARGE_INTEGER rWEPICVErrorCount; + LARGE_INTEGER rDecryptSuccessCount; + LARGE_INTEGER rDecryptFailureCount; +} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; + +/* Linux Network Device Statistics Struct */ +typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { + UINT_32 u4RxPackets; + UINT_32 u4TxPackets; + UINT_32 u4RxBytes; + UINT_32 u4TxBytes; + UINT_32 u4RxErrors; + UINT_32 u4TxErrors; + UINT_32 u4Multicast; +} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; + + +typedef struct _PARAM_MTK_WIFI_TEST_STRUC_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncData; +} PARAM_MTK_WIFI_TEST_STRUC_T, *P_PARAM_MTK_WIFI_TEST_STRUC_T; + + +/* 802.11 Media stream constraints */ +typedef enum _ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; + +/* for NDIS 5.1 Media Streaming Change */ +typedef struct _PARAM_MEDIA_STREAMING_INDICATION { + PARAM_STATUS_INDICATION_T rStatus; + ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; + + +#define PARAM_PROTOCOL_ID_DEFAULT 0x00 +#define PARAM_PROTOCOL_ID_TCP_IP 0x02 +#define PARAM_PROTOCOL_ID_IPX 0x06 +#define PARAM_PROTOCOL_ID_NBF 0x07 +#define PARAM_PROTOCOL_ID_MAX 0x0F +#define PARAM_PROTOCOL_ID_MASK 0x0F + +/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _PARAM_NETWORK_ADDRESS_IP +{ + UINT_16 sin_port; + UINT_32 in_addr; + UINT_8 sin_zero[8]; +} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; + +typedef struct _PARAM_NETWORK_ADDRESS { + UINT_16 u2AddressLength; // length in bytes of Address[] in this + UINT_16 u2AddressType; // type of this address (PARAM_PROTOCOL_ID_XXX above) + UINT_8 aucAddress[1]; // actually AddressLength bytes long +} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; + +// The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface + +typedef struct _PARAM_NETWORK_ADDRESS_LIST +{ + UINT_32 u4AddressCount; // number of addresses following + UINT_16 u2AddressType; // type of this address (NDIS_PROTOCOL_ID_XXX above) + PARAM_NETWORK_ADDRESS arAddress[1]; // actually AddressCount elements long +} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; + +#if CFG_SLT_SUPPORT + +#define FIXED_BW_LG20 0x0000 +#define FIXED_BW_UL20 0x2000 +#define FIXED_BW_DL40 0x3000 + +#define FIXED_EXT_CHNL_U20 0x4000 // For AGG register. +#define FIXED_EXT_CHNL_L20 0xC000 // For AGG regsiter. + +typedef enum _ENUM_MTK_LP_TEST_MODE_T { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; + +typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { + ENUM_MTK_SLT_FUNC_DO_NOTHING, + ENUM_MTK_SLT_FUNC_INITIAL, + ENUM_MTK_SLT_FUNC_RATE_SET, + ENUM_MTK_SLT_FUNC_LP_SET, + ENUM_MTK_SLT_FUNC_NUM +} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; + +typedef struct _PARAM_MTK_SLT_LP_TEST_STRUC_T { + ENUM_MTK_LP_TEST_MODE_T rLpTestMode; + UINT_32 u4BcnRcvNum; +} PARAM_MTK_SLT_LP_TEST_STRUC_T, *P_PARAM_MTK_SLT_LP_TEST_STRUC_T; + +typedef struct _PARAM_MTK_SLT_TR_TEST_STRUC_T { + ENUM_PARAM_NETWORK_TYPE_T rNetworkType; // Network Type OFDM5G or OFDM2.4G + UINT_32 u4FixedRate; // Fixed Rate including BW +} PARAM_MTK_SLT_TR_TEST_STRUC_T, *P_PARAM_MTK_SLT_TR_TEST_STRUC_T; + +typedef struct _PARAM_MTK_SLT_INITIAL_STRUC_T { + UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + UINT_16 u2SiteID; +} PARAM_MTK_SLT_INITIAL_STRUC_T, *P_PARAM_MTK_SLT_INITIAL_STRUC_T; + +typedef struct _PARAM_MTK_SLT_TEST_STRUC_T { + ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; + UINT_32 u4Length; /* Length of structure, + including myself */ + UINT_32 u4FuncInfoLen; /* Include following content + field and myself */ + union { + PARAM_MTK_SLT_INITIAL_STRUC_T rMtkInitTest; + PARAM_MTK_SLT_LP_TEST_STRUC_T rMtkLpTest; + PARAM_MTK_SLT_TR_TEST_STRUC_T rMtkTRTest; + } unFuncInfoContent; + +} PARAM_MTK_SLT_TEST_STRUC_T, *P_PARAM_MTK_SLT_TEST_STRUC_T; + +#endif + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_REGISTRY_FIXED_RATE_T { + FIXED_RATE_NONE, + FIXED_RATE_1M, + FIXED_RATE_2M, + FIXED_RATE_5_5M, + FIXED_RATE_11M, + FIXED_RATE_6M, + FIXED_RATE_9M, + FIXED_RATE_12M, + FIXED_RATE_18M, + FIXED_RATE_24M, + FIXED_RATE_36M, + FIXED_RATE_48M, + FIXED_RATE_54M, + FIXED_RATE_MCS0_20M_800NS, + FIXED_RATE_MCS1_20M_800NS, + FIXED_RATE_MCS2_20M_800NS, + FIXED_RATE_MCS3_20M_800NS, + FIXED_RATE_MCS4_20M_800NS, + FIXED_RATE_MCS5_20M_800NS, + FIXED_RATE_MCS6_20M_800NS, + FIXED_RATE_MCS7_20M_800NS, + FIXED_RATE_MCS0_20M_400NS, + FIXED_RATE_MCS1_20M_400NS, + FIXED_RATE_MCS2_20M_400NS, + FIXED_RATE_MCS3_20M_400NS, + FIXED_RATE_MCS4_20M_400NS, + FIXED_RATE_MCS5_20M_400NS, + FIXED_RATE_MCS6_20M_400NS, + FIXED_RATE_MCS7_20M_400NS, + FIXED_RATE_MCS0_40M_800NS, + FIXED_RATE_MCS1_40M_800NS, + FIXED_RATE_MCS2_40M_800NS, + FIXED_RATE_MCS3_40M_800NS, + FIXED_RATE_MCS4_40M_800NS, + FIXED_RATE_MCS5_40M_800NS, + FIXED_RATE_MCS6_40M_800NS, + FIXED_RATE_MCS7_40M_800NS, + FIXED_RATE_MCS32_800NS, + FIXED_RATE_MCS0_40M_400NS, + FIXED_RATE_MCS1_40M_400NS, + FIXED_RATE_MCS2_40M_400NS, + FIXED_RATE_MCS3_40M_400NS, + FIXED_RATE_MCS4_40M_400NS, + FIXED_RATE_MCS5_40M_400NS, + FIXED_RATE_MCS6_40M_400NS, + FIXED_RATE_MCS7_40M_400NS, + FIXED_RATE_MCS32_400NS, + FIXED_RATE_NUM +} ENUM_REGISTRY_FIXED_RATE_T, *P_ENUM_REGISTRY_FIXED_RATE_T; + +typedef enum _ENUM_BT_CMD_T { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +} ENUM_BT_CMD_T; + +typedef enum _ENUM_BT_PROFILE_T { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +} ENUM_BT_PROFILE_T; + +typedef struct _PTA_PROFILE_T { + ENUM_BT_PROFILE_T eBtProfile; + union { + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + /* 0: sco reserved slot time, + 1: sco idle slot time, + 2: acl throughput, + 3: bt tx power, + 4: bt rssi + 5: VoIP interval + 6: BIT(0) Use this field, BIT(1) 0 apply single/ 1 dual PTA setting. + */ + UINT_32 au4Btcr[4]; + } u; +} PTA_PROFILE_T, *P_PTA_PROFILE_T; + +typedef struct _PTA_IPC_T { + UINT_8 ucCmd; + UINT_8 ucLen; + union { + PTA_PROFILE_T rProfile; + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +} PARAM_PTA_IPC_T, *P_PARAM_PTA_IPC_T, PTA_IPC_T, *P_PTA_IPC_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ + +typedef struct _PARAM_SCAN_REQUEST_EXT_T { + PARAM_SSID_T rSsid; + UINT_32 u4IELength; + PUINT_8 pucIE; +} PARAM_SCAN_REQUEST_EXT_T, *P_PARAM_SCAN_REQUEST_EXT_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*--------------------------------------------------------------*/ +/* Routines to set parameters or query information. */ +/*--------------------------------------------------------------*/ +/***** Routines in wlan_oid.c *****/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryNetworkTypeInUse( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetNetworkTypeInUse ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryBssid( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetBssidListScan( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetBssidListScanExt ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryBssidList( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetBssid( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetSsid( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQuerySsid( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryInfrastructureMode( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetInfrastructureMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryAuthMode( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetAuthMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +#if 0 +WLAN_STATUS +wlanoidQueryPrivacyFilter ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + + +WLAN_STATUS +wlanoidSetPrivacyFilter ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +WLAN_STATUS +wlanoidSetEncryptionStatus( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryEncryptionStatus( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetAddWep( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetRemoveWep( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetAddKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetRemoveKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetReloadDefaults( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetTest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryCapability( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryFrequency ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetFrequency ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanoidQueryAtimWindow ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetAtimWindow ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanoidSetChannel ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryRssi( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryRssiTrigger( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetRssiTrigger( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryRtsThreshold ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetRtsThreshold ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSet802dot11PowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID prSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryPmkid( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetPmkid( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQuerySupportedRates( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryDesiredRates ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetDesiredRates ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryPermanentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, + IN UINT_32 u4QueryBufLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryCurrentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, + IN UINT_32 u4QueryBufLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryPermanentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, + IN UINT_32 u4QueryBufLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryMcrRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryMemDump ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetMcrWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanoidQuerySwCtrlRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetSwCtrlWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanoidQueryEepromRead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetEepromWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryRfTestRxStatus ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryRfTestTxStatus ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryOidInterfaceVersion ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryVendorId( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryMulticastList( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetMulticastList( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryRcvError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryRcvNoBuffer ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryRcvCrcError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryStatistics ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +#ifdef LINUX + +WLAN_STATUS +wlanoidQueryStatisticsForLinux ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +#endif + +WLAN_STATUS +wlanoidQueryMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryRcvOk( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryXmitOk( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryXmitError ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryXmitOneCollision ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryXmitMoreCollisions ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryXmitMaxCollisions ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + + +WLAN_STATUS +wlanoidSetCurrentPacketFilter( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryCurrentPacketFilter ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + + +WLAN_STATUS +wlanoidSetAcpiDevicePowerState ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + + +WLAN_STATUS +wlanoidSetDisassociate ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryFragThreshold ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetFragThreshold ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + + +WLAN_STATUS +wlanoidQueryAdHocMode ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetAdHocMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryBeaconInterval ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetBeaconInterval ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetCurrentAddr ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +WLAN_STATUS +wlanoidSetCSUMOffload ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen +); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +WLAN_STATUS +wlanoidSetNetworkAddress ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryMaxFrameSize ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryMaxTotalSize ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetCurrentLookahead ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +/* RF Test related APIs */ +WLAN_STATUS +wlanoidRftestSetTestMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidRftestSetAbortTestMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidRftestQueryAutoTest ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidRftestSetAutoTest ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +#if CFG_SUPPORT_WAPI +WLAN_STATUS +wlanoidSetWapiMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetWapiAssocInfo ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetWapiKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +#if CFG_SUPPORT_WPS2 +WLAN_STATUS +wlanoidSetWSCAssocInfo ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryEnableWakeup ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 u4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetEnableWakeup ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +WLAN_STATUS +wlanoidSetWiFiWmmPsTest ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetTxAmpdu ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetAddbaReject( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryNvramRead ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetNvramWrite ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryCfgSrcType( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryEepromType( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetCountryCode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanSendMemDumpCmd ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen + ); + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidUpdateSLTMode( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +#endif + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetOppPsParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetUApsdParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryBT ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetTxPower ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +/* +WLAN_STATUS +wlanoidQueryBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetPta ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryPta ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); +*/ + +#if CFG_ENABLE_WIFI_DIRECT +WLAN_STATUS +wlanoidSetP2pMode ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_OID_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h new file mode 100755 index 000000000000..c3c45094a9db --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h @@ -0,0 +1,461 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/wlan_p2p.h#3 $ +*/ + +/*! \file "wlan_p2p.h" + \brief This file contains the declairations of Wi-Fi Direct command + processing routines for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + + +/* +** $Log: wlan_p2p.h $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channle Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * support wlanoidSetP2pPowerSaveProfile() in P2P + * + * 08 16 2010 george.huang + * NULL + * Support wlanoidSetNetworkAddress() for P2P + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. + * + + * +** +*/ + +#ifndef _WLAN_P2P_H +#define _WLAN_P2P_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* Service Discovery */ +typedef struct _PARAM_P2P_SEND_SD_RESPONSE { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucChannelNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_SEND_SD_RESPONSE, *P_PARAM_P2P_SEND_SD_RESPONSE; + +typedef struct _PARAM_P2P_GET_SD_REQUEST { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_GET_SD_REQUEST, *P_PARAM_P2P_GET_SD_REQUEST; + +typedef struct _PARAM_P2P_GET_SD_REQUEST_EX { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 ucChannelNum; /* Channel Number Where SD Request is received. */ + UINT_8 ucSeqNum; /* Get SD Request by sequence number. */ + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_GET_SD_REQUEST_EX, *P_PARAM_P2P_GET_SD_REQUEST_EX; + +typedef struct _PARAM_P2P_SEND_SD_REQUEST { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucVersionNum; /* Indicate the Service Discovery Supplicant Version. */ + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_SEND_SD_REQUEST, *P_PARAM_P2P_SEND_SD_REQUEST; + +/* Service Discovery 1.0. */ +typedef struct _PARAM_P2P_GET_SD_RESPONSE { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_GET_SD_RESPONSE, *P_PARAM_P2P_GET_SD_RESPONSE; + +/* Service Discovery 2.0. */ +typedef struct _PARAM_P2P_GET_SD_RESPONSE_EX { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 ucSeqNum; /* Get SD Response by sequence number. */ + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} PARAM_P2P_GET_SD_RESPONSE_EX, *P_PARAM_P2P_GET_SD_RESPONSE_EX; + + +typedef struct _PARAM_P2P_TERMINATE_SD_PHASE { + PARAM_MAC_ADDRESS rPeerAddr; +} PARAM_P2P_TERMINATE_SD_PHASE, *P_PARAM_P2P_TERMINATE_SD_PHASE; + + +/*! \brief Key mapping of BSSID */ +typedef struct _P2P_PARAM_KEY_T +{ + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ + PARAM_KEY_RSC rKeyRSC; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} P2P_PARAM_KEY_T, *P_P2P_PARAM_KEY_T; + +#if CONFIG_NL80211_TESTMODE + +typedef struct _NL80211_DRIVER_TEST_PRE_PARAMS { + UINT_16 idx_mode; + UINT_16 idx; + UINT_32 value; +} NL80211_DRIVER_TEST_PRE_PARAMS, *P_NL80211_DRIVER_TEST_PRE_PARAMS; + + +typedef struct _NL80211_DRIVER_TEST_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_PARAMS, *P_NL80211_DRIVER_TEST_PARAMS; + + +/* P2P Sigma*/ +typedef struct _NL80211_DRIVER_P2P_SIGMA_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 idx; + UINT_32 value; +}NL80211_DRIVER_P2P_SIGMA_PARAMS, *P_NL80211_DRIVER_P2P_SIGMA_PARAMS; + + +/* Hotspot Client Management */ +typedef struct _NL80211_DRIVER_hotspot_block_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_8 ucblocked; + UINT_8 aucBssid[MAC_ADDR_LEN]; +}NL80211_DRIVER_hotspot_block_PARAMS, *P_NL80211_DRIVER_hotspot_block_PARAMS; + + +#if CFG_SUPPORT_WFD +typedef struct _NL80211_DRIVER_WFD_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 WfdCmdType; + UINT_8 WfdEnable; + UINT_8 WfdCoupleSinkStatus; + UINT_8 WfdSessionAvailable; + UINT_8 WfdSigmaMode; + UINT_16 WfdDevInfo; + UINT_16 WfdControlPort; + UINT_16 WfdMaximumTp; + UINT_16 WfdExtendCap; + UINT_8 WfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 WfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 WfdVideoIp[4]; + UINT_8 WfdAudioIp[4]; + UINT_16 WfdVideoPort; + UINT_16 WfdAudioPort; + UINT_32 WfdFlag; + UINT_32 WfdPolicy; + UINT_32 WfdState; + UINT_8 WfdSessionInformationIE[24*8]; // Include Subelement ID, length + UINT_16 WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 WfdAdvanceFlag; + UINT_8 aucWfdLocalIp[4]; + UINT_8 aucReserved2[64]; + UINT_8 aucReserved3[64]; + UINT_8 aucReserved4[64]; +}NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; +#endif + + + +#endif + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddP2PKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetRemoveP2PKey( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetNetworkAddress( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetP2PMulticastList( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSendP2PSDResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidGetP2PSDRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidGetP2PSDResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 puQueryInfoLen + ); + +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +#if CFG_SUPPORT_ANTI_PIRACY +WLAN_STATUS +wlanoidSetSecCheckRequest( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidGetSecCheckResponse( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); +#endif + +WLAN_STATUS +wlanoidSetNoaParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetOppPsParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetUApsdParam ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryP2pOpChannel( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidQueryP2pVersion( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi( + IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); +#endif + + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_P2P_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c new file mode 100755 index 000000000000..1d1479378e3a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c @@ -0,0 +1,1490 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#2 $ +*/ + +/*! \file "aaa_fsm.c" + \brief This file defines the FSM for AAA MODULE. + + This file defines the FSM for AAA MODULE. +*/ + + + +/* +** $Log: aaa_fsm.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 22 2012 yuche.tsai + * NULL + * Solve sigma test 5.1.3 issue, assoc response should have P2P IE. + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve inorder issue under AP mode. + * + * data frame may TX before assoc response frame. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 02 2011 eddie.chen + * [WCXRP00000759] [MT6620 Wi-Fi][DRV] Update RCPI in AAA + * Update RCPI when receiving Assoc request. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 09 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * Skip to call p2pRunEventAAAComplete to avoid indicate STA connect twice. + * + * 03 04 2011 terry.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * Remove unused variable. + * + * 02 16 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Add more check after RX assoc frame under Hot-Spot mode. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 15 2011 puff.wen + * NULL + * [On behalf of Frog] Add CFG_ENABLE_WIFI_DIRECT to p2pRunEventAAAComplete + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify AAA flow according to CM's comment. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 29 2010 yuche.tsai + * NULL + * Fix Compile warning, type cast from UINT_32 to UINT_16. + * + * 08 26 2010 yuche.tsai + * NULL + * In P2P AT GO test mode under WinXP, we would not indicate connected event to host. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 17 2010 yuche.tsai + * NULL + * Fix bug while enabling P2P GO. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * modify due to P2P functino call prototype change. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 04 02 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify CFG flags + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * add support of Driver STA_RECORD_T activation + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aaaFsmSendEventJoinComplete ( + WLAN_STATUS rJoinStatus, + P_STA_RECORD_T prStaRec, + P_SW_RFB_T prSwRfb + ) +{ + P_MSG_SAA_JOIN_COMP_T prJoinCompMsg; + + + ASSERT(prStaRec); + + prJoinCompMsg = cnmMemAlloc(RAM_TYPE_TCM, sizeof(MSG_SAA_JOIN_COMP_T)); + if (!prJoinCompMsg) { + return WLAN_STATUS_RESOURCES; + } + + if (IS_STA_IN_AIS(prStaRec)) { + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + } + else if (IS_STA_IN_P2P(prStaRec)) { + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + } + else if (IS_STA_IN_BOW(prStaRec)) { + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + } + else { + ASSERT(0); + } + + prJoinCompMsg->rJoinStatus = rJoinStatus; + prJoinCompMsg->prStaRec = prStaRec; + prJoinCompMsg->prSwRfb = prSwRfb; + + mboxSendMsg(MBOX_ID_0, + (P_MSG_HDR_T)prJoinCompMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmSendEventJoinComplete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to AAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aaaFsmRunEventStart ( + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + P_STA_RECORD_T prStaRec; + P_AIS_BSS_INFO_T prAisBssInfo; + + + ASSERT(prMsgHdr); + + prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T)prMsgHdr; + prStaRec = prJoinReqMsg->prStaRec; + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, ("EVENT-START: Trigger SAA FSM\n")); + + cnmMemFree(prMsgHdr); + + //4 <1> Validation of SAA Start Event + if (!IS_AP_STA(prStaRec->eStaType)) { + + DBGLOG(SAA, ERROR, ("EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType)); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + + //4 <2> The previous JOIN process is not completed ? + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, ("EVENT-START: Reentry of SAA Module.\n")); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + + //4 <3> Reset Status Code and Time + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T)NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T)NULL); + + return; +} /* end of saaFsmRunEventStart() */ +#endif + + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Request Frame and then +* trigger AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aaaFsmRunEventRxAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + UINT_16 u2StatusCode; + BOOLEAN fgReplyAuth = FALSE; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + + + ASSERT(prAdapter); + + do { + + + //4 <1> Check P2P network conditions +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered){ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prBssInfo->fgIsNetActive) { + + //4 <1.1> Validate Auth Frame by Auth Algorithm/Transation Seq + if (WLAN_STATUS_SUCCESS == + authProcessRxAuth1Frame(prAdapter, + prSwRfb, + prBssInfo->aucBSSID, + AUTH_ALGORITHM_NUM_OPEN_SYSTEM, + AUTH_TRANSACTION_SEQ_1, + &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + //4 <1.2> Validate Auth Frame for Network Specific Conditions + fgReplyAuth = p2pFuncValidateAuth( + prAdapter, + prSwRfb, + &prStaRec, + &u2StatusCode); + } + else { + fgReplyAuth = TRUE; + } + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + break; + } + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + //4 <2> Check BOW network conditions +#if CFG_ENABLE_BT_OVER_WIFI + { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if ((prBssInfo->fgIsNetActive) && + (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { + + //4 <2.1> Validate Auth Frame by Auth Algorithm/Transation Seq + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + authProcessRxAuth1Frame(prAdapter, + prSwRfb, + prBssInfo->aucBSSID, + AUTH_ALGORITHM_NUM_OPEN_SYSTEM, + AUTH_TRANSACTION_SEQ_1, + &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + + //4 <2.2> Validate Auth Frame for Network Specific Conditions + fgReplyAuth = bowValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); + + } + else { + + fgReplyAuth = TRUE; + } + eNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return; + } while (FALSE); + + if(prStaRec) { + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + } + + //4 <3> Update STA_RECORD_T and reply Auth_2(Response to Auth_1) Frame + if (fgReplyAuth) { + + if (prStaRec) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(AAA, WARN, ("Previous AuthAssocState (%d) != IDLE.\n", + prStaRec->eAuthAssocState)); + } + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + } + else { + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = u2StatusCode; + + prStaRec->ucAuthAlgNum = AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } + else { + /* NOTE(Kevin): We should have STA_RECORD_T if the status code was successful */ + ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); + } + + /* NOTE: Ignore the return status for AAA */ + //4 <4> Reply Auth + authSendAuthFrame(prAdapter, + prStaRec, + eNetTypeIndex, + prSwRfb, + AUTH_TRANSACTION_SEQ_2, + u2StatusCode); + + } + + return; +} /* end of aaaFsmRunEventRxAuth() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx (Re)Association Request Frame and then +* trigger AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aaaFsmRunEventRxAssoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + UINT_16 u2StatusCode = STATUS_CODE_RESERVED; + BOOLEAN fgReplyAssocResp = FALSE; + + + ASSERT(prAdapter); + + do { + + //4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + ASSERT(0); // Only for debug phase + break; + } + + if (!IS_CLIENT_STA(prStaRec)) { + break; + } + + if (prStaRec->ucStaState == STA_STATE_3) { + /* Do Reassocation */ + } + else if ((prStaRec->ucStaState == STA_STATE_2) && + (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { + /* Normal case */ + } + else { + DBGLOG(AAA, WARN, ("Previous AuthAssocState (%d) != SEND_AUTH2.\n", + prStaRec->eAuthAssocState)); + break; + } + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + //4 <2> Check P2P network conditions +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prBssInfo->fgIsNetActive) { + + //4 <2.1> Validate Assoc Req Frame and get Status Code + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + assocProcessRxAssocReqFrame(prAdapter, + prSwRfb, + &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + //4 <2.2> Validate Assoc Req Frame for Network Specific Conditions + fgReplyAssocResp = p2pFuncValidateAssocReq( + prAdapter, + prSwRfb, + (PUINT_16)&u2StatusCode); + } + else { + fgReplyAssocResp = TRUE; + } + + break; + } + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + //4 <3> Check BOW network conditions +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if ((prBssInfo->fgIsNetActive) && + (OP_MODE_BOW == prBssInfo->eCurrentOPMode)){ + + //4 <3.1> Validate Auth Frame by Auth Algorithm/Transation Seq + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + assocProcessRxAssocReqFrame(prAdapter, + prSwRfb, + &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + + //4 <3.2> Validate Auth Frame for Network Specific Conditions + fgReplyAssocResp = bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); + + } + else { + + fgReplyAssocResp = TRUE; + } + + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return WLAN_STATUS_SUCCESS; // To release the SW_RFB_T + } while (FALSE); + + + //4 <4> Update STA_RECORD_T and reply Assoc Resp Frame + if (fgReplyAssocResp) { + UINT_16 u2IELength; + PUINT_8 pucIE; + + if ((((P_WLAN_ASSOC_REQ_FRAME_T)(prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_REASSOC_REQ) { + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16)OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T)(prSwRfb->pvHeader))->aucInfoElem; + } + else { + u2IELength = prSwRfb->u2PacketLen - + (UINT_16)OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T)(prSwRfb->pvHeader))->aucInfoElem; + } + + rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); + + //4 <4.1> Assign Association ID + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + if (p2pRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + //prStaRec->eAuthAssocState = AA_STATE_IDLE; + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; // NOTE(Kevin): for TX done + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + //cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } + else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ + + /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if ((IS_STA_IN_BOW(prStaRec))) { + +// if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; // NOTE(Kevin): for TX done + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + //cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } +#if 0 + else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ + + /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif +#endif + } + else { + prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ + + /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = u2StatusCode; + + /* NOTE: Ignore the return status for AAA */ + //4 <4.2> Reply Assoc Resp + assocSendReAssocRespFrame(prAdapter, prStaRec); + + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventRxAssoc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth2/AssocReq) Event of AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aaaFsmRunEventTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(AAA, LOUD, ("EVENT-TX DONE: Current Time = %ld\n", kalGetTimeTick())); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + } + + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, + prMsduInfo, + AUTH_TRANSACTION_SEQ_2) != WLAN_STATUS_SUCCESS) { + break; + } + + if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { + if (TX_RESULT_SUCCESS == rTxDoneStatus) { + + /* NOTE(Kevin): Change to STATE_2 at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + else { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (IS_STA_IN_P2P(prStaRec))) { + p2pRunEventAAATxFail(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) { + bowRunEventAAATxFail(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + } + + } + /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ + + } + break; + + case AAA_STATE_SEND_ASSOC2: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocRespFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) { + break; + } + + if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { + if (TX_RESULT_SUCCESS == rTxDoneStatus) { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_3 at TX Done */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (IS_STA_IN_P2P(prStaRec))) { + p2pRunEventAAASuccess(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + + if (IS_STA_IN_BOW(prStaRec)) + { + bowRunEventAAAComplete(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + } + else { + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Change to STATE_2 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (IS_STA_IN_P2P(prStaRec))) { + p2pRunEventAAATxFail(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) { + bowRunEventAAATxFail(prAdapter, prStaRec); + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + } + } + /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ + } + break; + + default: + break; /* Ignore other cases */ + } + + + return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventTxDone() */ +#endif /* CFG_SUPPORT_AAA */ + + +#if 0 /* TODO(Kevin): for abort event, just reset the STA_RECORD_T. */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send ABORT Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventAbort ( + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, ("JOIN EVENT: ABORT\n")); + + + /* NOTE(Kevin): when reach here, the ARB_STATE should be in ARB_STATE_JOIN. */ + ASSERT(prJoinInfo->prBssDesc); + + //4 <1> Update Flags and Elements of JOIN Module. + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rJoinTimer); + + //4 <2> Update the associated STA_RECORD_T during JOIN. + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) { + + /* Update Station Record - Class 1 Flag */ + prStaRec->ucStaState = STA_STATE_1; + } +#if DBG + else { + ASSERT(0); /* Shouldn't happened, because we already add this STA_RECORD_T at JOIN_STATE_INIT */ + } +#endif /* DBG */ + + //4 <3> Pull back to IDLE. + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + //4 <4> If we are in Roaming, recover the settings of previous BSS. + /* NOTE: JOIN FAIL - + * Restore original setting from current BSS_INFO_T. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) { + joinAdoptParametersFromCurrentBss(prAdapter); + } + + return; +} /* end of joinFsmRunEventAbort() */ +#endif + + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +joinFsmRunEventJoinTimeOut ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, ("JOIN EVENT: JOIN TIMEOUT\n")); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) { + joinAdoptParametersFromCurrentBss(prAdapter); + } + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinAdoptParametersFromPeerBss ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + //4 <1> Adopt Peer BSS' PHY TYPE + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, ("Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS")); + + + //4 <2> Adopt Peer BSS' Frequency(Band/Channel) + DBGLOG(JOIN, INFO, ("Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand)); + + nicSwitchChannel(prAdapter, + prBssDesc->eBand, + prBssDesc->ucChannelNum, + 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + + return; +} /* end of joinAdoptParametersFromPeerBss() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinAdoptParametersFromCurrentBss ( + IN P_ADAPTER_T prAdapter + ) +{ + //P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; + P_BSS_INFO_T prBssInfo; + + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + //4 <1> Adopt current BSS' PHY TYPE + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + //4 <2> Adopt current BSS' Frequency(Band/Channel) + DBGLOG(JOIN, INFO, ("Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand)); + + nicSwitchChannel(prAdapter, + prBssInfo->eBand, + prBssInfo->ucChnl, + 10); + return; +} /* end of joinAdoptParametersFromCurrentBss() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinComplete ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +//4 <1> Update Connecting & Connected Flag of BSS_DESC_T. + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prAdapter->rConnSettings.aucSSID, + prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) { + prBssDesc->fgIsHiddenSSID = FALSE; + } +#if DBG + else { + ASSERT(0); + } +#endif /* DBG */ + + DBGLOG(JOIN, INFO, ("Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID)); + } + + +//4 <2> Update BSS_INFO_T from BSS_DESC_T + //4 <2.A> PHY Type + prBssInfo->ePhyType = prBssDesc->ePhyType; + + //4 <2.B> BSS Type + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + //4 <2.C> BSSID + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, ("JOIN to BSSID: ["MACSTR"]\n", MAC2STR(prBssDesc->aucBSSID))); + + + //4 <2.D> SSID + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + + //4 <2.E> Channel / Band information. + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + //4 <2.F> RSN/WPA information. + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) { + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + } + else { + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + } + + //4 <2.G> Beacon interval. + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + //4 <2.H> DTIM period. + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + //4 <2.I> ERP Information + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && // Our BSS's PHY_TYPE is ERP now. + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } + else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + //4 <2.J> Country inforamtion of the associated AP + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + //4 <2.K> Signal Power of the associated AP + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + //4 <2.L> Capability Field of the associated AP + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, ("prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi)); + + +//4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC + //4 <3.A> Association ID + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + //4 <3.B> WMM Infomation + if (prAdapter->fgIsEnableWMM && + (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T)); + } + else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } + else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + + //4 <3.C> Operational Rate Set & BSS Basic Rate Set + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + + //4 <3.D> Short Preamble + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) { + prBssInfo->fgUseShortPreamble = FALSE; + } + else { + prBssInfo->fgUseShortPreamble = TRUE; + } + } + else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } + else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, ("prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble)); + + + //4 <3.E> Short Slot Time + prBssInfo->fgUseShortSlotTime = + prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, ("prBssInfo->fgUseShortSlotTime = %d\n", + prBssInfo->fgUseShortSlotTime)); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + + //4 <3.F> Update Tx Rate for Control Frame + bssUpdateTxRateForControlFrame(prAdapter); + + + //4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). + //if (prAdapter->fgIsEnableRoaming) /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) { + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + } + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) { + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + } + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + + //4 <3.H> Update Parameter for TX Fragmentation Threshold +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + + +//4 <4> Update STA_RECORD_T + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + //4 <4.A> Desired Rate Set + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } + else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, + &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, + &prStaRec->ucCurrRate1Index)) { + ASSERT(0); + } + } + + DBGLOG(JOIN, INFO, ("prStaRec->ucCurrRate1Index = %d\n", + prStaRec->ucCurrRate1Index)); + + //4 <4.B> Preamble Mode + prStaRec->fgIsShortPreambleOptionEnable = + prBssInfo->fgUseShortPreamble; + + //4 <4.C> QoS Flag + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else { + ASSERT(0); + } +#endif /* DBG */ + + +//4 <5> Update NIC + //4 <5.A> Update BSSID & Operation Mode + nicSetupBSS(prAdapter, prBssInfo); + + //4 <5.B> Update WLAN Table. + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) { + ASSERT(FALSE); + } + + //4 <5.C> Update Desired Rate Set for BT. +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) { + txRateSetInitForBT(prAdapter, prStaRec); + } +#endif /* CFG_TX_FRAGMENT */ + + //4 <5.D> TX AC Parameter and TX/RX Queue Control + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } + else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, + prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + + #if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8)TXQ_DATA_MASK, (UINT_8)NULL); + #endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) { + nicTxRetransmitOfOsSendQue(prAdapter); + } + + #if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); + #endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + + +//4 <6> Setup CONNECTION flag. + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) { + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + } + else { + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, + (PVOID)NULL, + 0); + + return; +} /* end of joinComplete() */ +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c new file mode 100755 index 000000000000..c13c86081cea --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c @@ -0,0 +1,4641 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#1 $ +*/ + +/*! \file "aa_fsm.c" + \brief This file defines the FSM for SAA and AAA MODULE. + + This file defines the FSM for SAA and AAA MODULE. +*/ + + + +/* +** $Log: ais_fsm.c $ +** +** 11 15 2012 cp.wu +** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j +** do not try reconnecting when being disconnected by the peer + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED cases as an explicit trigger for Android framework + * correct reference to BSSID field in Association-Response frame. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED cases as an explicit trigger for Android framework + * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. + * 2. (Android only) when reassociation-and-non-roaming cases happened, indicate an extra DISCONNECT indication to Android Wi-Fi framework + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 10 26 2011 tsaiyuan.hsu + * [WCXRP00001064] [MT6620 Wi-Fi][DRV]] add code with roaming awareness when disconnecting AIS network + * be aware roaming when disconnecting AIS network. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * STA_REC shall be NULL for Beacon's MSDU + * + * 10 13 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS + * 1. short join failure count limit to 2 + * 2. treat join timeout as kind of join failure as well + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 20 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * change window registry of driver for roaming. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Handle client mode about preamble type and slot time + * + * 09 08 2011 tsaiyuan.hsu + * [WCXRP00000972] [MT6620 Wi-Fi][DRV]] check if roaming occurs after join failure to avoid state incosistence. + * check if roaming occurs after join failure to avoid deactivation of network. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 16 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * EnableRoaming in registry is deprecated. + * + * 08 16 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * use registry to enable or disable roaming. + * + * 07 07 2011 cp.wu + * [WCXRP00000840] [MT6620 Wi-Fi][Driver][AIS] Stop timer for joining when channel is released due to join failure count exceeding limit + * stop timer when joining operation is failed due to try count exceeds limitation + * + * 06 28 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * do not handle SCAN request immediately after connected to increase the probability of receiving 1st beacon frame. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * ensure DEAUTH is always sent before establish a new connection + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * typo fix: a right brace is missed. + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * When RECONNECT request is identified as disconnected, it is necessary to check for pending scan request. + * + * 06 16 2011 cp.wu + * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels + * mark fgIsTransition as TRUE for state rolling. + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * always check for pending scan after switched into NORMAL_TR state. + * + * 06 14 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * always treat connection request at higher priority over scanning request + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 05 18 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection + * change SCAN handling behavior when followed by a CONNECT/DISCONNECT requests by pending instead of dropping. + * + * 05 17 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection + * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 13 2011 george.huang + * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF + * remove assert + * + * 03 18 2011 cp.wu + * [WCXRP00000575] [MT6620 Wi-Fi][Driver][AIS] reduce memory usage when generating mailbox message for scan request + * when there is no IE needed for probe request, then request a smaller memory for mailbox message + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 03 11 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel + * + * 03 09 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * avoid clearing fgIsScanReqIssued so as to add scan results. + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 04 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * reset retry conter of attemp to connect to ap after completion of join. + * + * 03 04 2011 cp.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * surpress compile warning occured when compiled by GNU compiler collection. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 02 23 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach to improve response time for scanning request + * when handling reconnect request, set fgTryScan as TRUE + * + * 02 22 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach to improve response time for scanning request + * handle SCAN and RECONNECT with a FIFO approach. + * + * 02 09 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * Check if prRegInfo is null or not before initializing roaming parameters. + * + * 02 01 2011 cp.wu + * [WCXRP00000416] [MT6620 Wi-Fi][Driver] treat "unable to find BSS" as connection trial to prevent infinite reconnection trials + * treat "unable to find BSS" as connection trial to prevent infinite reconnection trials. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 14 2011 cp.wu + * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent + * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. + * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. + * + * 01 11 2011 cp.wu + * [WCXRP00000307] [MT6620 Wi-Fi][SQA]WHQL test .2c_wlan_adhoc case fail. + * [IBSS] when merged in, the bss state should be updated to firmware to pass WHQL adhoc failed item + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer when the corresponding BSS is disconnected due to beacon timeout + * remove from scanning result when the BSS is disconnected due to beacon timeout. + * + * 01 03 2011 cp.wu + * [WCXRP00000337] [MT6620 Wi-FI][Driver] AIS-FSM not to invoke cnmStaRecResetStatus directly 'cause it frees all belonging STA-RECs + * do not invoke cnmStaRecResetStatus() directly, nicUpdateBss will do the things after bss is disconnected + * + * 12 30 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * do not need to manipulate prStaRec after indicating BSS disconnection to firmware, 'cause all STA-RECs belongs to BSS has been freed already + * + * 12 27 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * add DEBUGFUNC() macro invoking for more detailed debugging information + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 17 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 25 2010 yuche.tsai + * NULL + * Update SLT Function for QoS Support and not be affected by fixed rate function. + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 14 2010 wh.su + * [WCXRP00000097] [MT6620 Wi-Fi] [Driver] Fixed the P2P not setting the fgIsChannelExt value make scan not abort + * initial the fgIsChannelExt value. + * + * 10 08 2010 cp.wu + * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. + * correct erroneous logic: specifying eBand with incompatible eSco + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 23 2010 cp.wu + * [WCXRP00000049] [MT6620 Wi-Fi][Driver] Adhoc cannot be created successfully. + * keep IBSS-ALONE state retrying until further instruction is received + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 09 2010 yuche.tsai + * NULL + * Fix NULL IE Beacon issue. Sync Beacon Content to FW before enable beacon. + * Both in IBSS Create & IBSS Merge + * + * 09 09 2010 cp.wu + * NULL + * frequency is in unit of KHz thus no need to divide 1000 once more. + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 25 2010 cp.wu + * NULL + * add option for enabling AIS 5GHz scan + * + * 08 25 2010 cp.wu + * NULL + * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, RLM/CNM will handle the channel switching when BSS information is updated + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 12 2010 cp.wu + * NULL + * check-in missed files. + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 09 2010 cp.wu + * NULL + * reset fgIsScanReqIssued when abort request is received right after join completion. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 cp.wu + * NULL + * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 29 2010 cp.wu + * NULL + * allocate on MGMT packet for IBSS beaconing. + * + * 07 29 2010 cp.wu + * NULL + * [AIS-FSM] fix: when join failed, release channel privilege as well + * + * 07 28 2010 cp.wu + * NULL + * reuse join-abort sub-procedure to reduce code size. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 26 2010 cp.wu + * + * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, just pend it til 5-sec. period finishes + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 26 2010 cp.wu + * + * re-commit code logic being overwriten. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 cp.wu + * + * 1) enable Ad-Hoc + * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. + * + * 07 23 2010 cp.wu + * + * indicate scan done for linux wireless extension + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 21 2010 cp.wu + * + * separate AIS-FSM states into different cases of channel request. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 20 2010 cp.wu + * + * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one + * 2) refine disconnection behaviour when issued during BG-SCAN process + * + * 07 20 2010 cp.wu + * + * 1) bugfix: do not stop timer for join after switched into normal_tr state, for providing chance for DHCP handshasking + * 2) modify rsnPerformPolicySelection() invoking + * + * 07 19 2010 cp.wu + * + * 1) init AIS_BSS_INFO as channel number = 1 with band = 2.4GHz + * 2) correct typo + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * for AIS scanning, driver specifies no extra IE for probe request + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 yarco.yang + * + * Remove CFG_MQM_MIGRATION + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Refine AIS-FSM by divided into more states + * + * 07 13 2010 cm.chang + * + * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * for first connection, if connecting failed do not enter into scan state. + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * once STA-REC is allocated and updated, invoke cnmStaRecChangeState() to sync. with firmware. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * remove unused definitions. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * RSN/PRIVACY compilation flag awareness correction + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change to enqueue TX frame infinitely. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 01 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add conditionial compiling flag to choose default available bandwidth + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile error if CFG_CMD_EVENT_VER_009 == 0 for prEventConnStatus->ucNetworkType. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 17 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Call pmAbort() and add ucNetworkType field in EVENT_CONNECTION_STATUS + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile warning - define of MQM_WMM_PARSING was removed + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed the use of compiling flag MQM_WMM_PARSING + * + * 04 27 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * + * Fix typo + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the protected bit at cap info for ad-hoc. + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add new HW CH macro support + * + * 04 07 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Add TX Power Control RCPI function. + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * move the wlan table alloc / free to change state function. + * + * 03 25 2010 wh.su + * [BORA00000676][MT6620] Support the frequency setting and query at build connection / connection event + * modify the build connection and status event structure bu CMD_EVENT doc 0.09 draft, default is disable. + * + * 03 24 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * fixed some WHQL testing error. + * + * 03 24 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Set / Unset POWER STATE in AIS Network + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 03 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add PHY_CONFIG to change Phy Type + * + * 03 03 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Use bcmWiFiNotify to replace wifi_send_msg to pass infomation to BCM module. + * + * 03 03 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Remove wmt_task definition and add PTA function. + * + * 03 02 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Init TXM and MQM testing procedures in aisFsmRunEventJoinComplete() + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Modified aisUpdateBssInfo() to call TXM's functions for setting WTBL TX parameters + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * clear the pmkid cache while indicate media disconnect. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * . + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Enabled MQM parsing WMM IEs for non-AP mode + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation + * + * 02 25 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * use the Rx0 dor event indicate. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Support dynamic channel selection + * + * 02 23 2010 wh.su + * [BORA00000621][MT6620 Wi-Fi] Add the RSSI indicate to avoid XP stalled for query rssi value + * Adding the RSSI event support, using the HAL function to get the rcpi value and tranlsate to RSSI and indicate to driver + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Set max AMDPU size supported by the peer to 64 KB, removed mqmInit() and mqmTxSendAddBaReq() function calls in aisUpdateBssInfo() + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 20 2010 kevin.huang + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags + * + * 01 15 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Configured the AMPDU factor to 3 for the APu1rwduu`wvpghlqg|q`mpdkb+ilp + * + * 01 14 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Add WiFi BCM module for the 1st time. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Refine JOIN Complete and seperate the function of Media State indication + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the sample code to update the wlan table rate, + * + * Dec 10 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Different function prototype of wifi_send_msg() + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call rlm related function to process HT info when join complete + * + * Dec 9 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * default the acquired wlan table entry code off + * + * Dec 9 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to acquired the wlan table entry, and a sample code to update the BA bit at table + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix the problem of prSwRfb overwrited by event packet in aisFsmRunEventJoinComplete() + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to integrate the security related code + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove redundant declaration + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add code for JOIN init and JOIN complete + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename u4RSSI to i4RSSI + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise ENUM_MEDIA_STATE to ENUM_PARAM_MEDIA_STATE + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add fgIsScanReqIssued to CONNECTION_SETTINGS_T + * + * Nov 26 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise Virtual CMD handler due to structure changed + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Virtual CMD & RESP for testing CMD PATH + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmInitializeConnectionSettings() + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_MGMT_FSM flag for aisFsmTest() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { + (PUINT_8)DISP_STRING("AIS_STATE_IDLE"), + (PUINT_8)DISP_STRING("AIS_STATE_SEARCH"), + (PUINT_8)DISP_STRING("AIS_STATE_SCAN"), + (PUINT_8)DISP_STRING("AIS_STATE_ONLINE_SCAN"), + (PUINT_8)DISP_STRING("AIS_STATE_LOOKING_FOR"), + (PUINT_8)DISP_STRING("AIS_STATE_WAIT_FOR_NEXT_SCAN"), + (PUINT_8)DISP_STRING("AIS_STATE_REQ_CHANNEL_JOIN"), + (PUINT_8)DISP_STRING("AIS_STATE_JOIN"), + (PUINT_8)DISP_STRING("AIS_STATE_IBSS_ALONE"), + (PUINT_8)DISP_STRING("AIS_STATE_IBSS_MERGE"), + (PUINT_8)DISP_STRING("AIS_STATE_NORMAL_TR"), + (PUINT_8)DISP_STRING("AIS_STATE_DISCONNECTING") +}; +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value of the connection settings for +* AIS network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisInitializeConnectionSettings ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucAnyBSSID[] = BC_BSSID; + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + int i = 0; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Setup default values for operation */ + COPY_MAC_ADDR(prConnSettings->aucMacAddress, aucZeroMacAddr); + + prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISCONNECT_SEC; + + COPY_MAC_ADDR(prConnSettings->aucBSSID, aucAnyBSSID); + prConnSettings->fgIsConnByBssidIssued = FALSE; + + prConnSettings->fgIsConnReqIssued = FALSE; + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + + prConnSettings->ucSSIDLen = 0; + + prConnSettings->eOPMode = NET_TYPE_INFRA; + + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + + if(prRegInfo) { + prConnSettings->ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4StartFreq); + prConnSettings->eAdHocBand = prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; + prConnSettings->eAdHocMode = (ENUM_PARAM_AD_HOC_MODE_T) (prRegInfo->u4AdhocMode); + } + + prConnSettings->eAuthMode = AUTH_MODE_OPEN; + + prConnSettings->eEncStatus = ENUM_ENCRYPTION_DISABLED; + + prConnSettings->fgIsScanReqIssued = FALSE; + + /* MIB attributes */ + prConnSettings->u2BeaconPeriod = DOT11_BEACON_PERIOD_DEFAULT; + + prConnSettings->u2RTSThreshold = DOT11_RTS_THRESHOLD_DEFAULT; + + prConnSettings->u2DesiredNonHTRateSet = RATE_SET_ALL_ABG; + + //prConnSettings->u4FreqInKHz; /* Center frequency */ + + + /* Set U-APSD AC */ + prConnSettings->bmfgApsdEnAc = PM_UAPSD_NONE; + + secInit(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* Features */ + prConnSettings->fgIsEnableRoaming = FALSE; +#if CFG_SUPPORT_ROAMING + if(prRegInfo) { + prConnSettings->fgIsEnableRoaming = ((prRegInfo->fgDisRoaming > 0)?(FALSE):(TRUE)); + } +#endif /* CFG_SUPPORT_ROAMING */ + + prConnSettings->fgIsAdHocQoSEnable = FALSE; + + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; + + /* Set default bandwidth modes */ + prConnSettings->uc2G4BandwidthMode = CONFIG_BW_20M; + prConnSettings->uc5GBandwidthMode = CONFIG_BW_20_40M; + + prConnSettings->rRsnInfo.ucElemId = 0x30; + prConnSettings->rRsnInfo.u2Version = 0x0001; + prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; + prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; + prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) + prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; + prConnSettings->rRsnInfo.u2RsnCap = 0; + prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; + + return; +} /* end of aisFsmInitializeConnectionSettings() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmInit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, INFO, ("->aisFsmInit()\n")); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + //4 <1> Initiate FSM + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T)NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + //4 <1.1> Initiate FSM - Timer INIT + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC)aisFsmRunEventBGSleepTimeOut, + (UINT_32)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC)aisFsmRunEventIbssAloneTimeOut, + (UINT_32)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + (PFN_MGMT_TIMEOUT_FUNC)aisPostponedEventOfDisconnTimeout, + (UINT_32)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC)aisFsmRunEventJoinTimeout, + (UINT_32)NULL); + + //4 <1.2> Initiate PWR STATE + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + + //4 <2> Initiate BSS_INFO_T - common part + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_AIS_INDEX); + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + //4 <3> Initiate BSS_INFO_T - private part + /* TODO */ + prAisBssInfo->eBand = BAND_2G4; + prAisBssInfo->ucPrimaryChannel = 1; + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + + //4 <4> Allocate MSDU_INFO_T for Beacon + prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prAisBssInfo->prBeacon) { + prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + } + else { + ASSERT(0); + } + +#if 0 + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + if (prAdapter->u4UapsdAcBmp == 0) { + prAdapter->u4UapsdAcBmp = CFG_INIT_UAPSD_AC_BMP; + //ASSERT(prAdapter->u4UapsdAcBmp); + } + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8)prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC =(UINT_8) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8)prAdapter->u4MaxSpLen; +#endif + + /* request list initialization */ + LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); + + //DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + //prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + //prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, + //prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); + + return; +} /* end of aisFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to uninitialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmUninit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, ("->aisFsmUninit()\n")); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + //4 <1> Stop all timers + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + //4 <2> flush pending request + aisFsmFlushRequest(prAdapter); + + //4 <3> Reset driver-domain BSS-INFO + if(prAisBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); + prAisBssInfo->prBeacon = NULL; + } + +#if CFG_SUPPORT_802_11W + rsnStopSaQuery(prAdapter); +#endif + + return; +} /* end of aisFsmUninit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateInit_JOIN ( + IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_JOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + ASSERT(prBssDesc); + + //4 <1> We are going to connect to this BSS. + prBssDesc->fgIsConnecting = TRUE; + + + //4 <2> Setup corresponding STA_RECORD_T + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + STA_TYPE_LEGACY_AP, + NETWORK_TYPE_AIS_INDEX, + prBssDesc); + + prAisFsmInfo->prTargetStaRec = prStaRec; + + //4 <2.1> sync. to firmware domain + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + //4 <3> Update ucAvailableAuthTypes which we can choice during SAA + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + prStaRec->fgIsReAssoc = FALSE; + + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: /* Note: Omit break here. */ + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8)AUTH_TYPE_OPEN_SYSTEM; + break; + + + case AUTH_MODE_SHARED: + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8)AUTH_TYPE_SHARED_KEY; + break; + + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(AIS, LOUD, ("JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n")); + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8)(AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SHARED_KEY); + break; + + default: + ASSERT(!(prConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); + DBGLOG(AIS, ERROR, ("JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", + prConnSettings->eAuthMode)); + /* TODO(Kevin): error handling ? */ + return; + } + + /* TODO(tyhsu): Assume that Roaming Auth Type is equal to ConnSettings eAuthMode */ + prAisSpecificBssInfo->ucRoamingAuthTypes = prAisFsmInfo->ucAvailableAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + } + else { + ASSERT(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE); + ASSERT(!prBssDesc->fgIsConnected); + + DBGLOG(AIS, LOUD, ("JOIN INIT: AUTH TYPE = %d for Roaming\n", + prAisSpecificBssInfo->ucRoamingAuthTypes)); + + + prStaRec->fgIsReAssoc = TRUE; /* We do roaming while the medium is connected */ + + /* TODO(Kevin): We may call a sub function to acquire the Roaming Auth Type */ + prAisFsmInfo->ucAvailableAuthTypes = prAisSpecificBssInfo->ucRoamingAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; + } + + + //4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes + if (prAisFsmInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, LOUD, ("JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n")); + prAisFsmInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } + else if (prAisFsmInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, LOUD, ("JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n")); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_SHARED_KEY; + } + else if (prAisFsmInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(AIS, LOUD, ("JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n")); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } + else { + ASSERT(0); + } + + //4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) + if (prConnSettings->eConnectionPolicy == CONNECT_BY_SSID_ANY) { + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + } + + //4 <6> Send a Msg to trigger SAA to start JOIN process. + prJoinReqMsg = (P_MSG_JOIN_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); // Can't trigger SAA FSM + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + if (1) { + int j; + P_FRAG_INFO_T prFragInfo; + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + //nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); + prFragInfo->pr1stFrag = (P_SW_RFB_T)NULL; + } + } + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + return; +} /* end of aisFsmInit_JOIN() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +aisFsmStateInit_RetryJOIN ( + IN P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) { + return FALSE; + } + + if (prAisFsmInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, INFO, ("RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n")); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_SHARED_KEY; + } + else { + DBGLOG(AIS, ERROR, ("RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n")); + ASSERT(0); + } + + prAisFsmInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); // Can't trigger SAA FSM + return FALSE; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + return TRUE; + +}/* end of aisFsmRetryJOIN() */ + + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_ALONE +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateInit_IBSS_ALONE ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + //4 <1> Check if IBSS was created before ? + if (prAisBssInfo->fgIsBeaconActivated) { + + //4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH +#if !CFG_SLT_SUPPORT + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); +#endif + } + + aisFsmCreateIBSS(prAdapter); + + return; +} /* end of aisFsmStateInit_IBSS_ALONE() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_MERGE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateInit_IBSS_MERGE ( + IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + + ASSERT(prBssDesc); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + //4 <1> We will merge with to this BSS immediately. + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + //4 <2> Setup corresponding STA_RECORD_T + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + STA_TYPE_ADHOC_PEER, + NETWORK_TYPE_AIS_INDEX, + prBssDesc); + + prStaRec->fgIsMerging = TRUE; + + prAisFsmInfo->prTargetStaRec = prStaRec; + + //4 <2.1> sync. to firmware domain + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + //4 <3> IBSS-Merge + aisFsmMergeIBSS(prAdapter, prStaRec); + + return; +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateAbort_JOIN ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_ABORT_T prJoinAbortMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = (P_MSG_JOIN_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + + ASSERT(0); // Can't abort SAA FSM + return; + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_CONNECT_INDICATION, + NULL, + 0); + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prJoinAbortMsg, + MSG_SEND_METHOD_BUF); + + /* 2. Return channel privilege */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + return; +} /* end of aisFsmAbortJOIN() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of SCAN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateAbort_SCAN ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Abort JOIN process. */ + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + + ASSERT(0); // Can't abort SCN FSM + return; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; + prScanCancelMsg->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_AIS_INDEX; +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + prScanCancelMsg->fgIsChannelExt = FALSE; + } +#endif + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prScanCancelMsg, + MSG_SEND_METHOD_UNBUF); + + return; +} /* end of aisFsmAbortSCAN() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateAbort_NORMAL_TR ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* TODO(Kevin): Do abort other MGMT func */ + + /* 1. Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + return; +} /* end of aisFsmAbortNORMAL_TR() */ + + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateAbort_IBSS ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + // reset BSS-DESC + if (prAisFsmInfo->prTargetStaRec) { + prBssDesc = scanSearchBssDescByTA(prAdapter, + prAisFsmInfo->prTargetStaRec->aucMacAddr); + + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + + // release channel privilege + aisFsmReleaseCh(prAdapter); + + return; +} +#endif /* CFG_SUPPORT_ADHOC */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) +* +* @param[in] eNextState Enum value of next AIS STATE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmSteps ( + IN P_ADAPTER_T prAdapter, + ENUM_AIS_STATE_T eNextState + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + P_MSG_CH_REQ_T prMsgChReq; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + P_AIS_REQ_HDR_T prAisReq; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + UINT_16 u2ScanIELen; + + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + +#if DBG + DBGLOG(AIS, STATE, ("TRANSITION: [%s] -> [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], + apucDebugAisState[eNextState])); +#else + DBGLOG(AIS, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n", + DBG_AIS_IDX, + prAisFsmInfo->eCurrentState, + eNextState)); +#endif + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prAisFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN)FALSE; + + /* Do tasks of the State that we just entered */ + switch (prAisFsmInfo->eCurrentState) { + /* NOTE(Kevin): we don't have to rearrange the sequence of following + * switch case. Instead I would like to use a common lookup table of array + * of function pointer to speed up state search. + */ + case AIS_STATE_IDLE: + + prAisReq = aisFsmGetNextRequest(prAdapter); + + if(prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (prConnSettings->fgIsConnReqIssued == TRUE && + prConnSettings->fgIsDisconnectedByNonRequest == FALSE) { + + prAisFsmInfo->fgTryScan = TRUE; + + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + // sync with firmware + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + + // reset trial count + prAisFsmInfo->ucConnTrialCount = 0; + + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } + else { + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + // sync with firmware + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + + // check for other pending request + if(prAisReq) { + if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_SCAN; + + fgIsTransition = TRUE; + } + } + } + + if(prAisReq) { + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + } + else if(prAisReq->eReqType == AIS_REQUEST_SCAN) { +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + wlanClearScanningResult(prAdapter); + + eNextState = AIS_STATE_SCAN; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + else if(prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; + + break; + + case AIS_STATE_SEARCH: + //4 <1> Search for a matched candidate and save it to prTargetBssDesc. +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + prBssDesc = scanSearchBssDescByPolicy(prAdapter, NETWORK_TYPE_AIS_INDEX); +#endif + + // we are under Roaming Condition. + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if(prAisFsmInfo->ucConnTrialCount > AIS_ROAMING_CONNECTION_TRIAL_LIMIT) { +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_CONNLIMIT); +#endif /* CFG_SUPPORT_ROAMING */ + // reset retry count + prAisFsmInfo->ucConnTrialCount = 0; + + // abort connection trial + prConnSettings->fgIsConnReqIssued = FALSE; + + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + + break; + } + } + + //4 <2> We are not under Roaming Condition. + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + //4 <2.a> If we have the matched one + if (prBssDesc) { + + //4 Stored the Selected BSS security cipher. For later asoc req compose IE + prAisBssInfo->u4RsnSelectedGroupCipher = + prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo->u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = + prBssDesc->u4RsnSelectedAKMSuite; + + //4 Do STATE transition and update current Operation Mode. + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + + // increase connection trial count + prAisFsmInfo->ucConnTrialCount++; + } +#if CFG_SUPPORT_ADHOC + else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + eNextState = AIS_STATE_IBSS_MERGE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + //4 <2.b> If we don't have the matched one + else { + + // increase connection trial count for infrastructure connection + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + prAisFsmInfo->ucConnTrialCount++; + } + + //4 Try to SCAN + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + } + //4 We've do SCAN already, now wait in some STATE. + else { + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* issue reconnect request, and retreat to idle state for scheduling */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } +#if CFG_SUPPORT_ADHOC + else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) + || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) + || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = NULL; + + eNextState = AIS_STATE_IBSS_ALONE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + } + } + //4 <3> We are under Roaming Condition. + else { // prAdapter->eConnectionState == MEDIA_STATE_CONNECTED. + + //4 <3.a> This BSS_DESC_T is our AP. + /* NOTE(Kevin 2008/05/16): Following cases will go back to NORMAL_TR. + * CASE I: During Roaming, APP(WZC/NDISTEST) change the connection + * settings. That make we can NOT match the original AP, so the + * prBssDesc is NULL. + * CASE II: The same reason as CASE I. Because APP change the + * eOPMode to other network type in connection setting + * (e.g. NET_TYPE_IBSS), so the BssDesc become the IBSS node. + * (For CASE I/II, before WZC/NDISTEST set the OID_SSID, it will change + * other parameters in connection setting first. So if we do roaming + * at the same time, it will hit these cases.) + * + * CASE III: Normal case, we can't find other candidate to roam + * out, so only the current AP will be matched. + * + * CASE VI: Timestamp of the current AP might be reset + */ + if ((!prBssDesc) || /* CASE I */ + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ + (prBssDesc->fgIsConnected) || /* CASE III */ + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)) /* CASE VI */) { +#if DBG + if ((prBssDesc) && + (prBssDesc->fgIsConnected)) { + ASSERT(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); + } +#endif /* DBG */ + /* We already associated with it, go back to NORMAL_TR */ + /* TODO(Kevin): Roaming Fail */ +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* Retreat to NORMAL_TR state */ + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + } + //4 <3.b> Try to roam out for JOIN this BSS_DESC_T. + else { +#if DBG + ASSERT(UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); +#endif /* DBG */ + + //4 Record the target BSS_DESC_T for next STATE. + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + // tyhsu: increase connection trial count + prAisFsmInfo->ucConnTrialCount++; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + } + } + + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, ("SCAN: Idle Begin - Current Time = %ld\n", kalGetTimeTick())); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prAisFsmInfo->u4SleepInterval < AIS_BG_SCAN_INTERVAL_MAX_SEC) { + prAisFsmInfo->u4SleepInterval <<= 1; + } + break; + + case AIS_STATE_SCAN: + case AIS_STATE_ONLINE_SCAN: + case AIS_STATE_LOOKING_FOR: + + if(!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + // sync with firmware + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + + /* IE length decision */ + if(prAisFsmInfo->u4ScanIELength > 0) { + u2ScanIELen = (UINT_16)prAisFsmInfo->u4ScanIELength; + } + else { +#if CFG_SUPPORT_WPS2 + u2ScanIELen = prAdapter->prGlueInfo->u2WSCIELen; +#else + u2ScanIELen = 0; +#endif + } + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF(MSG_SCN_SCAN_REQ, aucIE) + u2ScanIELen); + if (!prScanReqMsg) { + ASSERT(0); // Can't trigger SCAN FSM + return; + } + + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_AIS_INDEX; + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; +#endif + + if(prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + if(prAisFsmInfo->ucScanSSIDLen == 0) { + /* Scan for all available SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + } + else { + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + COPY_SSID(prScanReqMsg->aucSSID, + prScanReqMsg->ucSSIDLength, + prAisFsmInfo->aucScanSSID, + prAisFsmInfo->ucScanSSIDLen); + } + } + else { + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + COPY_SSID(prScanReqMsg->aucSSID, + prScanReqMsg->ucSSIDLength, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + } + + /* check if tethering is running and need to fix on specific channel */ + if(cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->ucChannelListNum = 1; + prScanReqMsg->arChnlInfoList[0].eBand + = eBand;; + prScanReqMsg->arChnlInfoList[0].ucChannelNum + = ucChannel; + } + else if(prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] == BAND_NULL) { + if(prAdapter->fgEnable5GBand == TRUE) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + } + else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } + } + else if(prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] == BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } + else if(prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] == BAND_5G) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } + else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + if(prAisFsmInfo->u4ScanIELength > 0) { + kalMemCopy(prScanReqMsg->aucIE, prAisFsmInfo->aucScanIEBuf, prAisFsmInfo->u4ScanIELength); + } + else { +#if CFG_SUPPORT_WPS2 + if(prAdapter->prGlueInfo->u2WSCIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, &prAdapter->prGlueInfo->aucWSCIE, prAdapter->prGlueInfo->u2WSCIELen); + } + } +#endif + + prScanReqMsg->u2IELen = u2ScanIELen; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prScanReqMsg, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ + + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); // Can't indicate CNM for channel acquiring + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prAisFsmInfo->prTargetBssDesc->aucBSSID); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChReq, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + break; + + case AIS_STATE_JOIN: + aisFsmStateInit_JOIN(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + aisFsmStateInit_IBSS_ALONE(prAdapter); + break; + + case AIS_STATE_IBSS_MERGE: + aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_NORMAL_TR: + if(prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* Don't do anything when rJoinTimeoutTimer is still ticking */ + } + else { + /* 1. Process for pending scan */ + if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming scan */ + else if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 3. Process for pending roaming scan */ + else if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + authSendDeauthFrame(prAdapter, + prAisBssInfo->prStaRecOfAP, + (P_SW_RFB_T)NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, + aisDeauthXmitComplete); + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + + } + } + while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventScanDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventScanDone()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + DBGLOG(AIS, LOUD, ("EVENT-SCAN DONE: Current Time = %ld\n", kalGetTimeTick())); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE)prMsgHdr; + ASSERT(prScanDoneMsg->ucNetTypeIndex == (UINT_8)NETWORK_TYPE_AIS_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + cnmMemFree(prAdapter, prMsgHdr); + + eNextState = prAisFsmInfo->eCurrentState; + + if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(AIS, WARN, ("SEQ NO of AIS SCN DONE MSG is not matched.\n")); + } + else { + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = AIS_STATE_IDLE; + + break; + + case AIS_STATE_ONLINE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ + + break; + + case AIS_STATE_LOOKING_FOR: +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_SEARCH; +#endif /* CFG_SUPPORT_ROAMING */ + break; + + default: + break; + + } + } + + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of aisFsmRunEventScanDone() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventAbort()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + //4 <1> Extract information of Abort Message and then free memory. + prAisAbortMsg = (P_MSG_AIS_ABORT_T)prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + + cnmMemFree(prAdapter, prMsgHdr); + +#if DBG + DBGLOG(AIS, LOUD, ("EVENT-ABORT: Current State %s\n", + apucDebugAisState[prAisFsmInfo->eCurrentState])); +#else + DBGLOG(AIS, LOUD, ("[%d] EVENT-ABORT: Current State [%d]\n", + DBG_AIS_IDX, + prAisFsmInfo->eCurrentState)); +#endif + + //4 <2> clear previous pending connection request and insert new one + if(ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED + || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + } + else { + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + } + + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + if(prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + //4 <3> invoke abort handler + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); + } + + return; +} /* end of aisFsmRunEventAbort() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handles AIS-FSM abort event/command +* +* \param[in] prAdapter Pointer of ADAPTER_T +* ucReasonOfDisconnect Reason for disonnection +* fgDelayIndication Option to delay disconnection indication +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmStateAbort ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucReasonOfDisconnect, + BOOLEAN fgDelayIndication + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + BOOLEAN fgIsCheckConnected; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + fgIsCheckConnected = FALSE; + + //4 <1> Save information of Abort Message and then free memory. + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + + //4 <2> Abort current job. + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IDLE: + case AIS_STATE_SEARCH: + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + /* Do cancel timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* queue for later handling */ + if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + + break; + + case AIS_STATE_LOOKING_FOR: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_JOIN: + /* Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + case AIS_STATE_IBSS_MERGE: + aisFsmStateAbort_IBSS(prAdapter); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_ONLINE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* queue for later handling */ + if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_NORMAL_TR: + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_DISCONNECTING: + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + break; + + default: + break; + } + + if (fgIsCheckConnected && + (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState)) { + + /* switch into DISCONNECTING state for sending DEAUTH if necessary */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && + prAisBssInfo->prStaRecOfAP && + prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); + + return; + } + else { + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + } + } + + aisFsmDisconnect(prAdapter, fgDelayIndication); + + return; + +} /* end of aisFsmStateAbort() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for AIS FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventJoinComplete ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T)prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + eNextState = prAisFsmInfo->eCurrentState; + + // Check State and SEQ NUM + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + P_BSS_INFO_T prAisBssInfo; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + // Check SEQ NUM + if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) { + + + //4 <1> JOIN was successful + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + + //1. Reset retry count + prAisFsmInfo->ucConnTrialCount = 0; + + // Completion of roaming + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_SUPPORT_ROAMING + //2. Deactivate previous BSS + aisFsmRoamingDisconnectPrevAP(prAdapter, prStaRec); + + //3. Update bss based on roaming staRec + aisUpdateBssInfoForRoamingAP(prAdapter, prStaRec, prAssocRspSwRfb); +#endif /* CFG_SUPPORT_ROAMING */ + } + else { + //4 <1.1> Change FW's Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + //4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. + if ((prAisBssInfo->prStaRecOfAP) && + (prAisBssInfo->prStaRecOfAP != prStaRec) && + (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { + + cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + } + + //4 <1.3> Update BSS_INFO_T + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + //4 <1.4> Activate current AP's STA_RECORD_T in Driver. + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + //4 <1.5> Update RSSI if necessary + nicUpdateRSSI(prAdapter, NETWORK_TYPE_AIS_INDEX, (INT_8)(RCPI_TO_dBm(prStaRec->ucRCPI)), 0); + + //4 <1.6> Indicate Connected Event to Host immediately. + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + } + +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventStart(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + //4 <1.7> Set the Next State of AIS FSM + eNextState = AIS_STATE_NORMAL_TR; + } + //4 <2> JOIN was not successful + else { + //4 <2.1> Redo JOIN process with other Auth Type if possible + if (aisFsmStateInit_RetryJOIN(prAdapter, prStaRec) == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* 1. Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* 2. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + if(prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + } + + /* 3.3 Free STA-REC */ + if(prStaRec != prAisBssInfo->prStaRecOfAP) { + cnmStaRecFree(prAdapter, prStaRec, FALSE); + } + + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { +#if CFG_SUPPORT_ROAMING + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING */ + } + else { + // abort connection trial + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_CONNECT_INDICATION, + NULL, + 0); + + eNextState = AIS_STATE_IDLE; + } + } + } + } +#if DBG + else { + DBGLOG(AIS, WARN, ("SEQ NO of AIS JOIN COMP MSG is not matched.\n")); + } +#endif /* DBG */ + + } + + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + if (prAssocRspSwRfb) { + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + } + + cnmMemFree(prAdapter, prMsgHdr); + + return; +} /* end of aisFsmRunEventJoinComplete() */ + + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Create which was sent by +* CNM to indicate that channel was changed for creating IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmCreateIBSS ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + do { + // Check State + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) { + aisUpdateBssInfoForCreateIBSS(prAdapter); + } + } + while (FALSE); + + return; +} /* end of aisFsmCreateIBSS() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Merge which was sent by +* CNM to indicate that channel was changed for merging IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* @param[in] prStaRec Pointer of STA_RECORD_T for merge +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmMergeIBSS ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + do { + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_MERGE: + { + P_BSS_DESC_T prBssDesc; + + //4 <1.1> Change FW's Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + //4 <1.2> Deactivate previous Peers' STA_RECORD_T in Driver if have. + bssClearClientList(prAdapter, prAisBssInfo); + + //4 <1.3> Unmark connection flag of previous BSS_DESC_T. + if ((prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID)) != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + + //4 <1.4> Update BSS_INFO_T + aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); + + //4 <1.5> Add Peers' STA_RECORD_T to Client List + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + + //4 <1.6> Activate current Peer's STA_RECORD_T in Driver. + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + //4 <1.7> Enable other features + + //4 <1.8> Indicate Connected Event to Host immediately. + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + //4 <1.9> Set the Next State of AIS FSM + eNextState = AIS_STATE_NORMAL_TR; + + //4 <1.10> Release channel privilege + aisFsmReleaseCh(prAdapter); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + } + while (FALSE); + + return; +} /* end of aisFsmMergeIBSS() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Notification of existing IBSS was found +* from SCN. +* +* @param[in] prMsgHdr Message of Notification of an IBSS was present. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventFoundIBSSPeer ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + BOOLEAN fgIsMergeIn; + + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T)prMsgHdr; + + ASSERT(prAisIbssPeerFoundMsg->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX); + + prStaRec = prAisIbssPeerFoundMsg->prStaRec; + ASSERT(prStaRec); + + fgIsMergeIn = prAisIbssPeerFoundMsg->fgIsMergeIn; + + cnmMemFree(prAdapter, prMsgHdr); + + + eNextState = prAisFsmInfo->eCurrentState; + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + { + //4 <1> An IBSS Peer 'merged in'. + if (fgIsMergeIn) { + + //4 <1.1> Change FW's Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + //4 <1.2> Add Peers' STA_RECORD_T to Client List + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + //4 <1.3> Mark connection flag of BSS_DESC_T. + if ((prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr)) != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } + else { + ASSERT(0); // Should be able to find a BSS_DESC_T here. + } + + //4 <1.4> Activate current Peer's STA_RECORD_T in Driver. + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + //4 <1.3> Mark connection flag of BSS_DESC_T. + if ((prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID)) != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } + else { + ASSERT(0); // Should be able to find a BSS_DESC_T here. + } + + + //4 <1.4> Activate current Peer's STA_RECORD_T in Driver. + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + //4 <1.6> sync. to firmware + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <1.7> Indicate Connected Event to Host immediately. + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + //4 <1.8> indicate PM for connected + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <1.9> Set the Next State of AIS FSM + eNextState = AIS_STATE_NORMAL_TR; + + //4 <1.10> Release channel privilege + aisFsmReleaseCh(prAdapter); + } + //4 <2> We need 'merge out' to this IBSS + else { + + //4 <2.1> Get corresponding BSS_DESC_T + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + //4 <2.2> Set the Next State of AIS FSM + eNextState = AIS_STATE_IBSS_MERGE; + } + } + break; + + case AIS_STATE_NORMAL_TR: + { + + //4 <3> An IBSS Peer 'merged in'. + if (fgIsMergeIn) { + + //4 <3.1> Add Peers' STA_RECORD_T to Client List + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + //4 <3.2> Activate current Peer's STA_RECORD_T in Driver. + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + //4 <3.2> Activate current Peer's STA_RECORD_T in Driver. + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + } + //4 <4> We need 'merge out' to this IBSS + else { + + //4 <4.1> Get corresponding BSS_DESC_T + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + //4 <4.2> Set the Next State of AIS FSM + eNextState = AIS_STATE_IBSS_MERGE; + + } + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of aisFsmRunEventFoundIBSSPeer() */ +#endif /* CFG_SUPPORT_ADHOC */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost ( + IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, + BOOLEAN fgDelayIndication + ) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + // NOTE(Kevin): Move following line to aisChangeMediaState() macro per CM's request. + //prAisBssInfo->eConnectionState = eConnectionState; + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) { + return; + } + } + + if (!fgDelayIndication) { + //4 <0> Cancel Delay Timer + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); + + //4 <1> Fill EVENT_CONNECTION_STATUS + rEventConnStatus.ucMediaStatus = (UINT_8)eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rEventConnStatus.ucInfraMode = (UINT_8)NET_TYPE_INFRA; + rEventConnStatus.u2AID = prAisBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } + else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (UINT_8)NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = prAisBssInfo->u2ATIMWindow; + } + else { + ASSERT(0); + } + + COPY_SSID(rEventConnStatus.aucSsid, + rEventConnStatus.ucSsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + COPY_MAC_ADDR(rEventConnStatus.aucBssid, prAisBssInfo->aucBSSID); + + rEventConnStatus.u2BeaconPeriod = prAisBssInfo->u2BeaconInterval; + rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prAisBssInfo->ucPrimaryChannel); + + switch (prAisBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_HR_DSSS_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (UINT_8)PARAM_NETWORK_TYPE_DS; + break; + } + } + else { + /* Deactivate previous Peers' STA_RECORD_T in Driver if have. */ + bssClearClientList(prAdapter, prAisBssInfo); + + #if CFG_PRIVACY_MIGRATION + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); + #endif + + rEventConnStatus.ucReasonOfDisconnect = prAisBssInfo->ucReasonOfDisconnect; + } + + //4 <2> Indication + nicMediaStateChange(prAdapter, NETWORK_TYPE_AIS_INDEX, &rEventConnStatus); + prAisBssInfo->eConnectionStateIndicated = eConnectionState; + } + else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(AIS, INFO, ("Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent)); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } + + return; +} /* end of aisIndicationOfMediaStateToHost() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisPostponedEventOfDisconnTimeout ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ) +{ + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + //4 <1> Deactivate previous AP's STA_RECORD_T in Driver if have. + if (prAisBssInfo->prStaRecOfAP) { + //cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + } + + //4 <2> Remove pending connection request + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + + //4 <3> Indicate Disconnected Event to Host immediately. + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); + + return; +} /* end of aisPostponedEventOfDisconnTimeout() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisUpdateBssInfoForJOIN ( + IN P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + P_SW_RFB_T prAssocRspSwRfb + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_BSS_DESC_T prBssDesc; + UINT_16 u2IELength; + PUINT_8 pucIE; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + + DBGLOG(AIS, INFO, ("Update AIS_BSS_INFO_T and apply settings to MAC\n")); + + + //3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings + //4 <1.1> Setup Operation Mode + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + //4 <1.2> Setup SSID + COPY_SSID(prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + //4 <1.3> Setup Channel, Band + prAisBssInfo->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prAisBssInfo->eBand = prAisFsmInfo->prTargetBssDesc->eBand; + + + //3 <2> Update BSS_INFO_T from STA_RECORD_T + //4 <2.1> Save current AP's STA_RECORD_T and current AID + prAisBssInfo->prStaRecOfAP = prStaRec; + prAisBssInfo->u2AssocId = prStaRec->u2AssocId; + + //4 <2.2> Setup Capability + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + } + else { + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + } + + //4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + + //3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) + //4 <3.1> Setup BSSID + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + + //4 <3.2> Parse WMM and setup QBSS flag + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prAisBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + //3 <4> Update BSS_INFO_T from BSS_DESC_T + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAssocRspFrame->aucBSSID); + if(prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + //4 <4.1> Setup MIB for current BSS + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + } + else { + // should never happen + ASSERT(0); + } + + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + + //4 <4.2> Update HT information and set channel + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + //4 <4.3> Sync with firmware for BSS-INFO + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked + //inside scanProcessBeaconAndProbeResp() after 1st beacon is received + + return; +} /* end of aisUpdateBssInfoForJOIN() */ + + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create an Ad-Hoc network and start sending Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisUpdateBssInfoForCreateIBSS ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prAisBssInfo->fgIsBeaconActivated) { + return; + } + + //3 <1> Update BSS_INFO_T per Network Basis + //4 <1.1> Setup Operation Mode + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + //4 <1.2> Setup SSID + COPY_SSID(prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + //4 <1.3> Clear current AP's STA_RECORD_T and current AID + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + prAisBssInfo->u2AssocId = 0; + + //4 <1.4> Setup Channel, Band and Phy Attributes + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + + prAisBssInfo->ucPhyTypeSet = + prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; /* Depend on eBand */ + + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } + else { + + prAisBssInfo->ucPhyTypeSet = + prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN; /* Depend on eBand */ + + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } + + //4 <1.5> Setup MIB for current BSS + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + +#if CFG_PRIVACY_MIGRATION + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } + else { + prAisBssInfo->fgIsProtection = FALSE; + } +#else + prAisBssInfo->fgIsProtection = FALSE; +#endif + + //3 <2> Update BSS_INFO_T common part + ibssInitForAdHoc(prAdapter, prAisBssInfo); + + + + //3 <3> Set MAC HW + //4 <3.1> Setup channel and bandwidth + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + //4 <3.2> use command packets to inform firmware + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <3.3> enable beaconing + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <3.4> Update AdHoc PM parameter + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //3 <4> Set ACTIVE flag. + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + + //3 <5> Start IBSS Alone Timer + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); + + return; + +} /* end of aisCreateIBSS() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the existing IBSS was found. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisUpdateBssInfoForMergeIBSS ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + //UINT_16 u2IELength; + //PUINT_8 pucIE; + + + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + + if (!prAisBssInfo->fgIsBeaconActivated) { + + //3 <1> Update BSS_INFO_T per Network Basis + //4 <1.1> Setup Operation Mode + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + //4 <1.2> Setup SSID + COPY_SSID(prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + //4 <1.3> Clear current AP's STA_RECORD_T and current AID + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + prAisBssInfo->u2AssocId = 0; + } + + //3 <2> Update BSS_INFO_T from STA_RECORD_T + //4 <2.1> Setup Capability + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use Peer's Cap Info as IBSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + prAisBssInfo->fgUseShortPreamble = TRUE; + } + else { + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + prAisBssInfo->fgUseShortPreamble = FALSE; + } + + // 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. + prAisBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + prAisBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + + if (prAisBssInfo->u2CapInfo & CAP_INFO_PRIVACY) { + prAisBssInfo->fgIsProtection= TRUE; + } + else { + prAisBssInfo->fgIsProtection = FALSE; + } + + //4 <2.2> Setup PHY Attributes and Basic Rate Set/Operational Rate Set + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + rateGetDataRatesFromRateSet(prAisBssInfo->u2OperationalRateSet, + prAisBssInfo->u2BSSBasicRateSet, + prAisBssInfo->aucAllSupportedRates, + &prAisBssInfo->ucAllSupportedRatesLen); + + //3 <3> X Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) + + + //3 <4> Update BSS_INFO_T from BSS_DESC_T + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + if(prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + //4 <4.1> Setup BSSID + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prBssDesc->aucBSSID); + + //4 <4.2> Setup Channel, Band + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + prAisBssInfo->eBand = prBssDesc->eBand; + + //4 <4.3> Setup MIB for current BSS + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; /* TBD(Kevin) */ + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + } + else { + // should never happen + ASSERT(0); + } + + + //3 <5> Set MAC HW + //4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU + { + UINT_8 ucLowestBasicRateIndex; + + if (!rateGetLowestRateIndexFromRateSet(prAisBssInfo->u2BSSBasicRateSet, + &ucLowestBasicRateIndex)) { + + if (prAisBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_OFDM) { + ucLowestBasicRateIndex = RATE_6M_INDEX; + } + else { + ucLowestBasicRateIndex = RATE_1M_INDEX; + } + } + + prAisBssInfo->ucHwDefaultFixedRateCode = + aucRateIndex2RateCode[prAisBssInfo->fgUseShortPreamble][ucLowestBasicRateIndex]; + } + + //4 <5.2> Setup channel and bandwidth + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + //4 <5.3> use command packets to inform firmware + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <5.4> enable beaconing + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //4 <5.5> Update AdHoc PM parameter + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + //3 <6> Set ACTIVE flag. + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + + return; +} /* end of aisUpdateBssInfoForMergeIBSS() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +aisValidateProbeReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + //4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8)((UINT_32)prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T)pucIE; + } + break; + } + } /* end of IE_FOR_EACH */ + + //4 <2> Check network conditions + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + if ((prIeSsid) && + ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, /* CURRENT SSID */ + prIeSsid->aucSSID, prIeSsid->ucLength)) ) { + fgReplyProbeResp = TRUE; + } + } + + return fgReplyProbeResp; + +} /* end of aisValidateProbeReq() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will modify and update necessary information to firmware +* for disconnection handling +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmDisconnect ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgDelayIndication + ) +{ + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); + +#if CFG_SUPPORT_ADHOC + if (prAisBssInfo->fgIsBeaconActivated) { + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_DELETE_ALL, + NETWORK_TYPE_AIS_INDEX, + 0, + NULL, + 0); + + prAisBssInfo->fgIsBeaconActivated = FALSE; + } +#endif + + rlmBssAborted(prAdapter, prAisBssInfo); + + //4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { + + if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) { + scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* remove from scanning results as well */ + wlanClearBssInScanningResult(prAdapter, prAisBssInfo->aucBSSID); + + /* trials for re-association */ + if (fgDelayIndication) { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + } + } + else { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + } + + if (fgDelayIndication) { + if (OP_MODE_IBSS != prAisBssInfo->eCurrentOPMode) { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } + else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } + else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + + + //4 <4> Change Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + //4 <4.1> sync. with firmware + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (!fgDelayIndication) { + //4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. + if (prAisBssInfo->prStaRecOfAP) { + //cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + } + } + +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter); + + /* clear pending roaming connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); +#endif /* CFG_SUPPORT_ROAMING */ + + //4 <6> Indicate Disconnected Event to Host + aisIndicationOfMediaStateToHost(prAdapter, + PARAM_MEDIA_STATE_DISCONNECTED, + fgDelayIndication); + + + //4 <7> Trigger AIS FSM + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + + return; +} /* end of aisFsmDisconnect() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventBGSleepTimeOut ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, ("EVENT - SCAN TIMER: Idle End - Current Time = %ld\n", kalGetTimeTick())); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of aisFsmBGSleepTimeout() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventIbssAloneTimeOut ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch(prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + + /* There is no one participate in our AdHoc during this TIMEOUT Interval + * so go back to search for a valid IBSS again. + */ + + DBGLOG(AIS, LOUD, ("EVENT-IBSS ALONE TIMER: Start pairing\n")); + + prAisFsmInfo->fgTryScan = TRUE; + + /* abort timer */ + aisFsmReleaseCh(prAdapter); + + /* Pull back to SEARCH to find candidate again */ + eNextState = AIS_STATE_SEARCH; + + break; + + default: + break; + } + + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of aisIbssAloneTimeOut() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventJoinTimeout ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch(prAisFsmInfo->eCurrentState) { + case AIS_STATE_JOIN: + DBGLOG(AIS, LOUD, ("EVENT- JOIN TIMEOUT\n")); + + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* 2. Increase Join Failure Count */ + prAisFsmInfo->prTargetStaRec->ucJoinFailureCount++; +// For JB nl802.11 +#if 0 + if(prAisFsmInfo->prTargetStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) { + /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ + eNextState = AIS_STATE_SEARCH; + } + else { + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } +#endif + eNextState = AIS_STATE_IDLE; + break; + + case AIS_STATE_NORMAL_TR: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + /* 2. process if there is pending scan */ + if(aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + } + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + } + + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) { + aisFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of aisFsmRunEventJoinTimeout() */ + + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisTest ( + VOID + ) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucSSID[]="pci-11n"; + UINT_8 ucSSIDLen=7; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Set Connection Request Issued Flag */ + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->ucSSIDLen = ucSSIDLen; + kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); + + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + + ASSERT(0); // Can't trigger SCAN FSM + return; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + + wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); + + return; +} +#endif /* CFG_TEST_MGMT_FSM */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prSsid Pointer of SSID_T if specified +* \param[in] pucIe Pointer to buffer of extra information elements to be attached +* \param[in] u4IeLength Length of information elements +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmScanRequest ( + IN P_ADAPTER_T prAdapter, + IN P_PARAM_SSID_T prSsid, + IN PUINT_8 pucIe, + IN UINT_32 u4IeLength + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(prAdapter); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + + if(prSsid == NULL) { + prAisFsmInfo->ucScanSSIDLen = 0; + } + else { + COPY_SSID(prAisFsmInfo->aucScanSSID, + prAisFsmInfo->ucScanSSIDLen, + prSsid->aucSsid, + (UINT_8)prSsid->u4SsidLen); + } + + if(u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH ) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + if(NULL !=pucIe) + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } + else { + prAisFsmInfo->u4ScanIELength = 0; + } + + if(prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if(prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + // 802.1x might not finished yet, pend it for later handling .. + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + else { + if(prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, ("Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, + prAisFsmInfo->fgIsChannelRequested)); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } + else if(prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } + else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } + else { + DBGLOG(AIS, WARN, ("Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState)); + } + + return; +} /* end of aisFsmScanRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventChGrant ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_GRANT_T prMsgChGrant; + UINT_8 ucTokenID; + UINT_32 u4GrantInterval; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T)prMsgHdr; + + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + + if(prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && + prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + + /* 3. state transition to join/ibss-alone/ibss-merge */ + /* 3.1 set timeout timer in cases join could not be completed */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + prAisFsmInfo->u4ChGrantedInterval - AIS_JOIN_CH_GRANT_THRESHOLD); + /* 3.2 set local variable to indicate join timer is ticking */ + prAisFsmInfo->fgIsInfraChannelFinished = FALSE; + + /* 3.3 switch to join state */ + aisFsmSteps(prAdapter, AIS_STATE_JOIN); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } + else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + aisFsmReleaseCh(prAdapter); + } + + return; +} /* end of aisFsmRunEventChGrant() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmReleaseCh ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if(prAisFsmInfo->fgIsChannelGranted == TRUE + || prAisFsmInfo->fgIsChannelRequested == TRUE) { + + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); // Can't release Channel to CNM + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChAbort, + MSG_SEND_METHOD_BUF); + } + + return; +} /* end of aisFsmReleaseCh() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that corresponding beacon has not +* been received for a while and probing is not successful +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisBssBeaconTimeout ( + IN P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prAisBssInfo; + BOOLEAN fgDoAbortIndication = FALSE; + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + //4 <1> Diagnose Connection for Beacon Timeout Event + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { + if (OP_MODE_INFRASTRUCTURE == prAisBssInfo->eCurrentOPMode) { + P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec) { + fgDoAbortIndication = TRUE; + } + } + else if (OP_MODE_IBSS == prAisBssInfo->eCurrentOPMode) { + fgDoAbortIndication = TRUE; + } + } + + //4 <2> invoke abort handler + if (fgDoAbortIndication) { + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); + } + + return; +} /* end of aisBssBeaconTimeout() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that DEAUTH frame has been +* sent and thus state machine could go ahead +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prMsduInfo Pointer of MSDU_INFO_T for DEAUTH frame +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aisDeauthXmitComplete ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if(prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + if(rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER) { + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_NEW_CONNECTION, FALSE); + } + } + else { + DBGLOG(AIS, WARN, ("DEAUTH frame transmitted without further handling")); + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aisDeauthXmitComplete() */ + +#if CFG_SUPPORT_ROAMING +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Looking for a candidate due to weak signal" to AIS FSM. +* +* @param[in] u4ReqScan Requesting Scan or not +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRunEventRoamingDiscovery ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4ReqScan + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_AIS_REQUEST_TYPE_T eAisRequest; + + DBGLOG(AIS, LOUD, ("aisFsmRunEventRoamingDiscovery()\n")); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* search candidates by best rssi */ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter); + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } + else { + if(prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } + else { + eAisRequest = AIS_REQUEST_ROAMING_SEARCH; + } + } + + if(prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + if(eAisRequest == AIS_REQUEST_ROAMING_SEARCH) { + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); + } + else { + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } + } + else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + + aisFsmInsertRequest(prAdapter, eAisRequest); + } + + return; +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the time of ScanDone for roaming and transit to Roam state. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +ENUM_AIS_STATE_T +aisFsmRoamingScanResultsUpdate ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DBGLOG(AIS, LOUD, ("->aisFsmRoamingScanResultsUpdate()\n")); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + roamingFsmScanResultsUpdate(prAdapter); + + eNextState = prAisFsmInfo->eCurrentState; + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { + roamingFsmRunEventRoam(prAdapter); + eNextState = AIS_STATE_SEARCH; + } + else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eNextState = AIS_STATE_SEARCH; + } + else if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + eNextState = AIS_STATE_NORMAL_TR; + } + + return eNextState; +} /* end of aisFsmRoamingScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will modify and update necessary information to firmware +* for disconnection of last AP before switching to roaming bss. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prTargetStaRec Target of StaRec of roaming +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmRoamingDisconnectPrevAP ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prTargetStaRec + ) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, LOUD, ("aisFsmRoamingDisconnectPrevAP()")); + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* Not invoke rlmBssAborted() here to avoid prAisBssInfo->fg40mBwAllowed + * to be reset. RLM related parameters will be reset again when handling + * association response in rlmProcessAssocRsp(). 20110413 + */ + //rlmBssAborted(prAdapter, prAisBssInfo); + + //4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + } + + //4 <4> Change Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + //4 <4.1> sync. with firmware + prTargetStaRec->ucNetTypeIndex = 0xff; /* Virtial NetType */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + prTargetStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Virtial NetType */ + + return; +} /* end of aisFsmRoamingDisconnectPrevAP() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the roaming was completed. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prStaRec StaRec of roaming AP +* prAssocRspSwRfb +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisUpdateBssInfoForRoamingAP ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prAssocRspSwRfb + ) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, LOUD, ("aisUpdateBssInfoForRoamingAP()")); + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + //4 <1.1> Change FW's Media State immediately. + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + //4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. + if ((prAisBssInfo->prStaRecOfAP) && + (prAisBssInfo->prStaRecOfAP != prStaRec) && + (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { + cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + } + + //4 <1.3> Update BSS_INFO_T + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + //4 <1.4> Activate current AP's STA_RECORD_T in Driver. + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + //4 <1.6> Indicate Connected Event to Host immediately. + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + return; +} /* end of aisFsmRoamingUpdateBss() */ + +#endif /* CFG_SUPPORT_ROAMING */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any pending request and remove it (optional) +* +* @param prAdapter +* eReqType +* bRemove +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +aisFsmIsRequestPending ( + IN P_ADAPTER_T prAdapter, + IN ENUM_AIS_REQUEST_TYPE_T eReqType, + IN BOOLEAN bRemove + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* traverse through pending request list */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, + prPendingReqHdrNext, + &(prAisFsmInfo->rPendingReqList), + rLinkEntry, + AIS_REQ_HDR_T) { + /* check for specified type */ + if(prPendingReqHdr->eReqType == eReqType) { + /* check if need to remove */ + if(bRemove == TRUE) { + LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo->rPendingReqList), &(prPendingReqHdr->rLinkEntry)); + + cnmMemFree(prAdapter, prPendingReqHdr); + } + + return TRUE; + } + } + + return FALSE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get next pending request +* +* @param prAdapter +* +* @return P_AIS_REQ_HDR_T +*/ +/*----------------------------------------------------------------------------*/ +P_AIS_REQ_HDR_T +aisFsmGetNextRequest ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); + + return prPendingReqHdr; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Insert a new request +* +* @param prAdapter +* eReqType +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +aisFsmInsertRequest ( + IN P_ADAPTER_T prAdapter, + IN ENUM_AIS_REQUEST_TYPE_T eReqType + ) +{ + P_AIS_REQ_HDR_T prAisReq; + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + prAisReq = (P_AIS_REQ_HDR_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(AIS_REQ_HDR_T)); + + if(!prAisReq) { + ASSERT(0); // Can't generate new message + return FALSE; + } + + prAisReq->eReqType = eReqType; + + /* attach request into pending request list */ + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Flush all pending requests +* +* @param prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisFsmFlushRequest ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_REQ_HDR_T prAisReq; + + ASSERT(prAdapter); + + while((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) { + cnmMemFree(prAdapter, prAisReq); + } + + return; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c new file mode 100755 index 000000000000..d91d19743e92 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c @@ -0,0 +1,2050 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#3 $ +*/ + +/*! \file "assoc.c" + \brief This file includes the association-related functions. + + This file includes the association-related functions. +*/ + + + +/*\ +** $Log: assoc.c $ +** +** 07 27 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Fix wifi direct connection issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 06 08 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * add a pair of brace for compilation success. + * + * 06 04 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * discussed with WH, privacy bit in associate response is not necessary to be checked, and identified as association failure when mismatching with beacon/probe response + * + * 03 14 2012 wh.su + * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting + * Add code from 2.2 + * + * 03 09 2012 terry.wu + * NULL + * Fix build error. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 yuche.tsai + * NULL + * Update Driver for wifi driect gc join IE update issue. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Fix PhyTypeSet in STA_REC in AP mode + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 19 2011 yuche.tsai + * NULL + * Fix KE when enable hot-spot & any one client connect to this hot-spot. + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 07 15 2011 terry.wu + * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment + * Update workaround for Kingnet AP. + * + * 07 15 2011 terry.wu + * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment + * Workaround for Kingnet 710 AP wrong AID assignment. + * + * 05 02 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning[WCXRP00000672] [MT6620 Wi-Fi][FW] Fix the PS event allocation + * Check STA when rx assoc. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 03 14 2011 wh.su + * [WCXRP00000545] [MT6620 Wi-Fi] [Driver] Fixed the p2p not enable, received a assoc rsp cause the rx assoc execute a null function + * Modify file for avoid assert at BOW recieve a assoc response frame but no p2p fucntion. + * + * 03 08 2011 terry.wu + * [WCXRP00000524] [MT6620 Wi-Fi][Driver] Fix p2p assoc request containing wrong IE format + * Fix p2p assoc request containing wrong IE format. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix RX disassoc issue under Hot-spot mode. + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Update Phy Type Set. When legacy client is connected, it can use 11b rate, + * but if the P2P device is connected, 11b rate is not allowed. + * + * 01 11 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Update Desired Non-HT Rate Set. + * + * 12 30 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Recover the code that was coverwritted.. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 yuche.tsai + * NULL + * Add SSID IE in assoc req frame which is sent by P2P GC. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RSN IE generation by CFG_RSN_MIGRATION compilation flag. + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * revised. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update assocProcessRxAssocReqFrame() to avoid redundant SSID IE {0,0} for IOT. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile warning - macro > 10 line, initial value of an array + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * * * * * * and will send Null frame to diagnose connection + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * adding the wpa-none for ibss beacon. + * + * 03 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 28 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * fixed the compiling warning.u1rwduu`wvpghlqg|rm+vp + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update Assoc ID for PS + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Use new constant definition ELEM_MAX_LEN_EXT_CAP + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Modify assoc req IE talbe for HT cap IE + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * update the assocComposeReAssocReqFrameHeader() and fix the u2EstimatedFrameLen in assocSendReAssocReqFrame() + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove some space line + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the sending disassoc frame function + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the txassocReq IE table, adding for WPA/RSN + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix eNetType not init in send AssocReq function + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Integrate the send Assoc with TXM + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to indicate the assoc request and assoc response (now disable) + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove unused variables + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +APPEND_VAR_IE_ENTRY_T txAssocReqIETable[] = { + { (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmReqGenerateHtCapIE },/* 45 */ +#if CFG_SUPPORT_WPS2 + { (ELEM_HDR_LEN + ELEM_MAX_LEN_WSC), NULL, rsnGenerateWSCIE }, /* 221 */ +#endif +#if CFG_SUPPORT_WAPI + { (ELEM_HDR_LEN + ELEM_MAX_LEN_WAPI), NULL, wapiGenerateWAPIIE }, /* 68 */ +#endif +#if CFG_RSN_MIGRATION + { (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE }, /* 221 */ +#endif + { (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE }, /* 127 */ + { (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE }, /* 221 */ +#if CFG_RSN_MIGRATION + { (ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE }, /* 48 */ +#endif +}; + +#if CFG_SUPPORT_AAA +VERIFY_IE_ENTRY_T rxAssocReqIETable[] = { + { ELEM_ID_RESERVED, NULL } /* 255 */ +}; + + +APPEND_VAR_IE_ENTRY_T txAssocRespIETable[] = { + { (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE }, /* 42 */ + { (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE }, /* 45 */ + { (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE }, /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + { (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE }, /* 74 */ + { (0), p2pFuncCalculateP2p_IELenForAssocRsp, p2pFuncGenerateP2p_IEForAssocRsp }, /* 221 */ +#if CFG_SUPPORT_WFD + { (0), wfdFuncCalculateWfdIELenForAssocRsp, wfdFuncGenerateWfdIEForAssocRsp }, /* 221 */ +#endif +#endif + { (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE }, /* 127 */ + { (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE }, /* 221 */ + + { (0), p2pFuncCalculateWSC_IELenForAssocRsp, p2pFuncGenerateWSC_IEForAssocRsp } /* 221 */ + +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose the Capability Info Field. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval Capability Info Field +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ UINT_16 +assocBuildCapabilityInfo ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + UINT_32 u4NonHTPhyType; + UINT_16 u2CapInfo; + + + ASSERT(prStaRec); + + + /* Set up our requested capabilities. */ + u2CapInfo = CAP_INFO_ESS; + u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; + + if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) { + u2CapInfo |= CAP_INFO_PRIVACY; + } + + + /* 7.3.1.4 */ + if (prStaRec->fgHasBasicPhyType) { + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + if ( (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && + ( (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) && + (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) ) ) { + + /* Case I: Implemented == TRUE and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE and Short Preamble == AUTO (depends on + * BSS_DESC_T's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } + + if (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortSlotTimeOptionImplemented && + prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) { + u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + } + + DBGLOG(SAA, LOUD, ("ASSOC REQ: Compose Capability = 0x%04x for Target BSS ["MACSTR"].\n", + u2CapInfo, MAC2STR(prStaRec->aucMacAddr))); + + + return u2CapInfo; + +} /* end of assocBuildCapabilityInfo() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +assocBuildReAssocReqFrameCommonIEs ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + PUINT_8 pucBuffer; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM] = {0}; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if(!prStaRec) { + return; + } + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (IS_STA_IN_AIS(prStaRec)) { + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + } +#if CFG_ENABLE_WIFI_DIRECT + else if((prAdapter->fgIsP2PRegistered) && + (IS_STA_IN_P2P(prStaRec))) { + pucBuffer = p2pBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo, pucBuffer); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +#endif + + else { + /* TODO(Kevin): For other network */ + } + + /* NOTE(Kevin 2008/12/19): 16.3.6.3 MLME-ASSOCIATE.indication - + * SupportedRates - The set of data rates that are supported by the STA + * that is requesting association. + * Original(Portable Driver): Only send the Rates that we'll support. + * New: Send the Phy Rates if the result of following & operation == NULL. + */ + //rateGetDataRatesFromRateSet((prBssDesc->u2OperationalRateSet & + // rPhyAttributes[prBssDesc->ePhyType].u2SupportedRateSet), + + if (prStaRec->fgHasBasicPhyType) { + UINT_32 u4NonHTPhyType; + + + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + u2SupportedRateSet = (prStaRec->u2OperationalRateSet & + rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet); + + ASSERT(u2SupportedRateSet); + + if (!u2SupportedRateSet) { + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + } + + /* TODO(Kevin): For P2P, we shouldn't send support rate set which contains 11b rate */ + + rateGetDataRatesFromRateSet(u2SupportedRateSet, + 0, + aucAllSupportedRates, + &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, + aucAllSupportedRates, + ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + } + + return; +} /* end of assocBuildReAssocReqFrameCommonIEs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Request frame header and +* its fixed fields +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +assocComposeReAssocReqFrameHeaderAndFF ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, + IN UINT_8 aucMACAddress[], + IN OUT PUINT_16 pu2PayloadLen + ) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + UINT_16 u2CapInfo; + UINT_16 u2ListenInterval; + + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + ASSERT(pu2PayloadLen); + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T)pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + //4 <1> Compose the frame header of the (Re)Association Request frame. + /* Fill the Frame Control field. */ + if (fgIsReAssoc) { + u2FrameCtrl = MAC_FRAME_REASSOC_REQ; + } + else { + u2FrameCtrl = MAC_FRAME_ASSOC_REQ; + } + WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocFrame->u2SeqCtrl = 0; + + + //4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + + /* Fill the Capability Information field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); + + + /* Calculate the listen interval for the maximum power mode. Currently, we + set it to the value 2 times DTIM period. */ + if (prStaRec->ucDTIMPeriod) { + u2ListenInterval = prStaRec->ucDTIMPeriod * DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD; + } + else { + DBGLOG(SAA, TRACE, ("Use default listen interval\n")); + u2ListenInterval = DEFAULT_LISTEN_INTERVAL; + } + prStaRec->u2ListenInterval = u2ListenInterval; + + /* Fill the Listen Interval field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2ListenInterval, u2ListenInterval); + + + //4 <3> Compose the Current AP Address field for ReAssociation Request frame. + /* Fill the Current AP Address field. */ + if (prStaRec->fgIsReAssoc) { + if (IS_STA_IN_AIS(prStaRec)) { + + P_AIS_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + P_WLAN_REASSOC_REQ_FRAME_T prReAssocFrame = + (P_WLAN_REASSOC_REQ_FRAME_T)prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, prAisBssInfo->aucBSSID); + } + else { + ASSERT(0); /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN); + } + else { + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + + LISTEN_INTERVAL_FIELD_LEN); + } + + return; +} /* end of assocComposeReAssocReqFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Request frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocSendReAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + + ASSERT(prStaRec); + + //4 <1> Allocate a PKT_INFO_T for Authentication Frame + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + if (fgIsReAssoc) { + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_MGMT_HEADER_LEN + \ + CAP_INFO_FIELD_LEN + \ + LISTEN_INTERVAL_FIELD_LEN + \ + CURR_AP_ADDR_FIELD_LEN + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + \ + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + } + else { + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_MGMT_HEADER_LEN + \ + CAP_INFO_FIELD_LEN + \ + LISTEN_INTERVAL_FIELD_LEN + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + \ + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + } + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + if ((prAdapter->fgIsP2PRegistered)) { + u2EstimatedExtraIELen = p2pCalculate_IEForAssocReq(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + else { + DBGLOG(P2P, TRACE, ("Function Linker Lost.\n")); + ASSERT(FALSE); + } + } + else { + for (i = 0; i < sizeof(txAssocReqIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; + } + else { + u2EstimatedExtraIELen += (UINT_16)txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + } + } +#else + for (i = 0; i < sizeof(txAssocReqIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; + } + else { + u2EstimatedExtraIELen += (UINT_16)txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + } +#endif + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SAA, WARN, ("No PKT_INFO_T for sending (Re)Assoc Request.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, + &u2PayloadLen); + + //4 <3> Update information of MSDU_INFO_T + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Compose the frame body's IEs of the (Re)Association Request frame. + assocBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo); + + + //4 <5> Compose IEs in MSDU_INFO_T +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + if ((prAdapter->fgIsP2PRegistered)) { + p2pGenerate_IEForAssocReq(prAdapter, prMsduInfo); + } + else { + DBGLOG(P2P, TRACE, ("Function Linker Lost.\n")); + ASSERT(FALSE); + } + } + else { + /* Append IE */ + for (i = 0; i < sizeof(txAssocReqIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].pfnAppendIE) { + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + } +#else + /* Append IE */ + for (i = 0; i < sizeof(txAssocReqIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].pfnAppendIE) { + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } +#endif + + //4 <6> Update the (Re)association request information + if (IS_STA_IN_AIS(prStaRec)) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + +#if CFG_RSN_MIGRATION + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (PUINT_8)&prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); +#endif + } + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + + kalP2PUpdateAssocInfo( + prAdapter->prGlueInfo, + (PUINT_8)&prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + //4 <6> Enqueue the frame to send this (Re)Association request frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendReAssocReqFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Request frame for +* SAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocCheckTxReAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T)(prMsduInfo->prPacket); + ASSERT(prAssocReqFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + //WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2TxFrameCtrl) + u2TxFrameCtrl = prAssocReqFrame->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_REQ) { + return WLAN_STATUS_FAILURE; + } + } + else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_REQ) { + return WLAN_STATUS_FAILURE; + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocReqFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Response frame for +* AAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocCheckTxReAssocRespFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T)(prMsduInfo->prPacket); + ASSERT(prAssocRspFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + //WLAN_GET_FIELD_16(&prAssocFrame->u2FrameCtrl, &u2TxFrameCtrl) + u2TxFrameCtrl = prAssocRspFrame->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_RSP) { + return WLAN_STATUS_FAILURE; + } + } + else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_RSP) { + return WLAN_STATUS_FAILURE; + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocRespFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming (Re)Association Frame and take out +* the status code. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + UINT_16 u2RxFrameCtrl; + UINT_16 u2RxCapInfo; + UINT_16 u2RxStatusCode; + UINT_16 u2RxAssocId; + + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, ("prSwRfb->u2PayloadLength = %d\n", prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + //4 <1> locate the (Re)Assocation Resp Frame. + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Header of (Re)Assocation Resp Frame. + //WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) { + return WLAN_STATUS_FAILURE; + } + } + else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) { + return WLAN_STATUS_FAILURE; + } + } + + //4 <3> Parse the Fixed Fields of (Re)Assocation Resp Frame Body. + //WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); + u2RxCapInfo = prAssocRspFrame->u2CapInfo; // NOTE(Kevin): Optimized for ARM + + //WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); + u2RxStatusCode = prAssocRspFrame->u2StatusCode; // NOTE(Kevin): Optimized for ARM + + //4 <4> Check CAP_INFO + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs didn't check + * the CAP Privacy Bit to overcome a corner case that the Privacy Bit + * of our SCAN result didn't consist with AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + /* WAPI AP allow the customer use WZC to join mode, the privacy bit is 0 */ + /* even at WAI & WAPI_PSK mode, but the assoc respose set the privacy bit set 1 */ + DBGLOG(SEC, TRACE, ("Workaround the WAPI AP allow the customer to use WZC to join\n")); + } + else +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && 1) { + /* Todo:: Fixed this */ + } + else +#endif + { + } + +#if CFG_STRICT_CHECK_CAPINFO_PRIVACY + if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ (u2RxCapInfo & CAP_INFO_PRIVACY)) { + u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + } +#endif + } + + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_RSN_MIGRATION + /* Update the information in the structure used to query and set + OID_802_11_ASSOCIATION_INFORMATION. */ + kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, + (PUINT_8)&prAssocRspFrame->u2CapInfo, + (UINT_32)(prSwRfb->u2PacketLen)); +#endif + } + + //4 <5> Update CAP_INFO and ASSOC_ID + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { + prStaRec->u2CapInfo = u2RxCapInfo; + + //WLAN_GET_FIELD_16(&prAssocRspFrame->u2AssocId, &u2RxAssocId); + u2RxAssocId = prAssocRspFrame->u2AssocId; // NOTE(Kevin): Optimized for ARM + + /* 20110715 Workaround for Kingnet 710 AP (Realtek 8186) + * This AP raises the bit 6&7 not bit 14&15 in AID field. + * It cause wrong AID assignment. + * For AID = 2 + * Normal case: 0xC002(1100 0000 0000 0010) => 2 + * Kingnet 710: 0x00C2(0000 0000 1100 0010) => 194 + * workaround: mask bit 6&7 for this AP + */ + if((u2RxAssocId & BIT(6)) && + (u2RxAssocId & BIT(7)) && + !(u2RxAssocId & BITS(8, 15))) { + prStaRec->u2AssocId = u2RxAssocId & ~BITS(6,7); + } else { + prStaRec->u2AssocId = u2RxAssocId & ~AID_MSB; +#if CFG_SUPPORT_802_11W + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prBssSpecInfo->ucSaQueryTimedOut = 0; + } +#endif + } + } + +#if CFG_SUPPORT_802_11W + if (u2RxStatusCode == STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED){ + DBGLOG(SAA, INFO, ("AP rejected due the authentication algorithm not support\n")); + } + else if (u2RxStatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + PUINT_8 pucIE, pucTime; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8)((UINT_32)prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_TIMEOUT_INTERVAL == IE_ID(pucIE) && IE_LEN(pucIE) == 5) { + pucTime = ((P_IE_HDR_T)pucIE)->aucInfo; + if (pucTime[0] == ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + UINT_32 tu; + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, ("AP rejected association temporarily; comeback duration %u TU " + "(%u ms)\n", tu, TU_TO_MSEC(tu))); + if (tu > TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, ("Update timer based on comeback duration\n")); + //ieee80211_reschedule_timer(wpa_s, ms); + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will compose the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2ReasonCode The reason code of disassociation +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +assocComposeDisassocFrame ( + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, + IN UINT_8 aucMACAddress[], + IN UINT_16 u2ReasonCode + ) +{ + P_WLAN_DISASSOC_FRAME_T prDisAssocFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + + prDisAssocFrame = (P_WLAN_DISASSOC_FRAME_T)pucBuffer; + + //4 <1> Compose the frame header of the DisAssociation frame. + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DISASSOC; + + WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDisAssocFrame->u2SeqCtrl = 0; + + //4 <2> Compose the frame body's fixed field part of the Disassociation frame. + /* Fill the Reason Code field. */ + WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); + + return; +} /* end of assocComposeDisassocFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2ReasonCode The reason code of disassociation +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocSendDisAssocFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_16 u2ReasonCode + ) +{ + PUINT_8 pucMacAddress; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + //UINT_32 u4Status = WLAN_STATUS_SUCCESS; + + + ASSERT(prStaRec); + + //4 <1> Allocate a PKT_INFO_T for Disassociation Frame + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_MGMT_HEADER_LEN + \ + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SAA, WARN, ("No PKT_INFO_T for sending DisAssoc.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose Disassociation frame header and fixed fields in MSDU_INfO_T. + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + pucMacAddress = prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucMacAddress, + u2ReasonCode); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + prDisassocFrame = (P_WLAN_DEAUTH_FRAME_T)(PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, ("assocSendDisAssocFrame with protection\n")); + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + //4 <3> Update information of MSDU_INFO_T + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Enqueue the frame to send this (Re)Association request frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendDisAssocFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Disassociation frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocProcessRxDisassocFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucBSSID[], + OUT PUINT_16 pu2ReasonCode + ) +{ + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + UINT_16 u2RxReasonCode; + + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + //4 <1> locate the Disassociation Frame. + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Header of Disassociation Frame. + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDisassocFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, ("Ignore Disassoc Frame from other BSS ["MACSTR"]\n", + MAC2STR(prDisassocFrame->aucSrcAddr))); + return WLAN_STATUS_FAILURE; + } + + //4 <3> Parse the Fixed Fields of Deauthentication Frame Body. + WLAN_GET_FIELD_16(&prDisassocFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxDisassocFrame() */ + + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Association Req frame +* and return a Status Code. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code for carried in Association Response. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocProcessRxAssocReqFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL; + P_RSN_INFO_ELEM_T prIeRsn = (P_RSN_INFO_ELEM_T)NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T)NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T)NULL; + PUINT_8 pucIE, pucIEStart; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_16 u2StatusCode = STATUS_CODE_SUCCESSFUL; + UINT_16 u2RxFrameCtrl; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + UINT_32 i; + + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + return WLAN_STATUS_FAILURE; + } + + //4 <1> locate the Association Req Frame. + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Header of Association Req Frame. + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prAssocReqFrame->aucBSSID, prBssInfo->aucBSSID)) { + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + } + + //WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2RxFrameCtrl); + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (MAC_FRAME_REASSOC_REQ == u2RxFrameCtrl) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16)(OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T)(prSwRfb->pvHeader))->aucInfoElem; + } + else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16)(OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + + //4 <3> Parse the Fixed Fields of Assoc Req Frame Body. + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) && + !kalP2PGetCipher(prAdapter->prGlueInfo))) { + u2StatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + DBGLOG(RSN, TRACE, ("STA Assoc req privacy bit check fail\n")); + return WLAN_STATUS_SUCCESS; + } + } +#endif + + prStaRec->u2ListenInterval = prAssocReqFrame->u2ListenInterval; + prStaRec->ucPhyTypeSet = 0; + + /* Might be legacy client or p2p gc. */ + prStaRec->eStaType = STA_TYPE_LEGACY_CLIENT; + + //4 <4> Parse the IE of Assoc Req Frame Body. + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): Get SSID once */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T)pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) { + prIeSupportedRate = SUP_RATES_IE(pucIE); + } + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + if (!prIeExtSupportedRate) + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + case ELEM_ID_HT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + break; + case ELEM_ID_RSN: + #if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + prIeRsn = RSN_IE(pucIE); + rsnParserCheckForRSNCCMPPSK(prAdapter, prIeRsn, &u2StatusCode); + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } + #endif + break; + case ELEM_ID_VENDOR: + #if CFG_ENABLE_WIFI_DIRECT + { + if ((prAdapter->fgIsP2PRegistered)) { + UINT_8 ucOuiType = 0; + + p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType); + + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + DBGLOG(P2P, TRACE, ("Target Client is a P2P group client\n")); + prStaRec->eStaType = STA_TYPE_P2P_GC; + } + } + } + #endif + break; + default: + for (i = 0; i < (sizeof(rxAssocReqIETable) / sizeof(VERIFY_IE_ENTRY_T)); i++) { + + if ((IE_ID(pucIE)) == rxAssocReqIETable[i].ucElemID) { + rxAssocReqIETable[i].pfnVarifyIE(prAdapter, prSwRfb, (P_IE_HDR_T)pucIE, &u2StatusCode); + + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } + } + + break; + } + } /* end of IE_FOR_EACH */ + + // parsing for WMM related information (2010/12/21) + mqmProcessAssocReq( + prAdapter, + prSwRfb, + pucIEStart, + u2IELength); + + do { + if (prIeSsid) { + if (UNEQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + + u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; + break; + } + } + else { + u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; + break; + } + + prStaRec->u2OperationalRateSet = 0; + prStaRec->u2BSSBasicRateSet = 0; + + if (prIeSupportedRate || prIeExtSupportedRate) { + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &prStaRec->u2OperationalRateSet, + &u2BSSBasicRateSet, /* Ignore any Basic Bit */ + &fgIsUnknownBssBasicRate); + + if ((prBssInfo->u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) != + prBssInfo->u2BSSBasicRateSet) { + + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + + /* Accpet the Sta, update BSSBasicRateSet from Bss */ + + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); + + if (BAND_2G4 == HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr)) { + #if 0 /* Marked by CMC 20111024 */ + /* check if support 11n */ + if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + } + + + if (!(u2BSSBasicRateSet & RATE_SET_OFDM)) { + if (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + } + + } + + } + #else + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + } + if (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + } + #endif + } + else { /* (BAND_5G == prBssDesc->eBande) */ + #if 0 /* Marked by CMC 20111024 */ + if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + ASSERT((prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) == 0); + #else + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + #endif + } + + } + else { + ASSERT(0); + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher(prAdapter->prGlueInfo)) { + u2StatusCode = STATUS_CODE_CIPHER_SUITE_REJECTED; + break; + } + } + else { + prStaRec->rSecInfo.fgAllowOnly1x = FALSE; + if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + //Only Allow 1x + prStaRec->rSecInfo.fgAllowOnly1x = TRUE; + break; + } + } + } +#endif + + } while (FALSE); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + #if 1 /* ICS */ + { + PUINT_8 cp = (PUINT_8)&prAssocReqFrame->u2CapInfo; + if (prStaRec->fgIsReAssoc) + cp += 10; + else + cp += 4; + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + } + prStaRec->u2AssocReqIeLen = u2IELength; + if (u2IELength) { + prStaRec->pucAssocReqIe = kalMemAlloc(u2IELength, VIR_MEM_TYPE); + kalMemCopy(prStaRec->pucAssocReqIe, cp, u2IELength); + } + } + #endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, (PUINT_8)&prAssocReqFrame->u2CapInfo, u2IELength + (prStaRec->fgIsReAssoc ? 10 : 4), prStaRec->fgIsReAssoc); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +assocBuildReAssocRespFrameCommonIEs ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_BSS_INFO_T prBssInfo + ) +{ + PUINT_8 pucBuffer; + P_STA_RECORD_T prStaRec; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } + else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, + prBssInfo->aucAllSupportedRates, + ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + + return; +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Response frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucBssid Given BSSID. +* @param[in] u2CapInfo Capability Field of current BSS. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +assocComposeReAssocRespFrameHeaderAndFF ( + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, + IN UINT_8 aucBSSID[], + IN UINT_16 u2CapInfo, + IN OUT PUINT_16 pu2PayloadLen + ) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucBSSID); + ASSERT(pu2PayloadLen); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T)pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + //4 <1> Compose the frame header of the (Re)Association Request frame. + /* Fill the Frame Control field. */ + if (fgIsReAssoc) { + u2FrameCtrl = MAC_FRAME_REASSOC_RSP; + } + else { + u2FrameCtrl = MAC_FRAME_ASSOC_RSP; + } + //WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); + prAssocRspFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the DA field with Target MAC Address. */ + COPY_MAC_ADDR(prAssocRspFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucSrcAddr, aucBSSID); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucBSSID, aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocRspFrame->u2SeqCtrl = 0; + + + //4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. + /* Fill the Capability Information field. */ + //WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); + prAssocRspFrame->u2CapInfo = u2CapInfo; // NOTE(Kevin): Optimized for ARM + + //WLAN_SET_FIELD_16(&prAssocFrame->u2StatusCode, prStaRec->u2StatusCode); + prAssocRspFrame->u2StatusCode = prStaRec->u2StatusCode; // NOTE(Kevin): Optimized for ARM + + //WLAN_SET_FIELD_16(&prAssocFrame->u2AssocId, ((prStaRec->u2AssocId & AID_MASK) | AID_MSB)); + prAssocRspFrame->u2AssocId = + ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); // NOTE(Kevin): Optimized for ARM + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN); + + return; +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Resp frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocSendReAssocRespFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + + ASSERT(prStaRec); + + + //4 <1> Allocate a PKT_INFO_T for Authentication Frame + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_MGMT_HEADER_LEN + \ + CAP_INFO_FIELD_LEN + \ + STATUS_CODE_FIELD_LEN + \ + AID_FIELD_LEN + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + \ + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAssocRespIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocRespIETable[i].u2EstimatedFixedIELen; + } + else if (txAssocRespIETable[i].pfnCalculateVariableIELen != NULL) { + u2EstimatedExtraIELen += (UINT_16)txAssocRespIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(AAA, WARN, ("No PKT_INFO_T for sending (Re)Assoc Response.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. + ASSERT(prStaRec->ucNetTypeIndex != NETWORK_TYPE_AIS_INDEX); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, + prBssInfo->u2CapInfo, + &u2PayloadLen); + + //4 <3> Update information of MSDU_INFO_T + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = aaaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Compose the frame body's IEs of the (Re)Association Request frame. + assocBuildReAssocRespFrameCommonIEs(prAdapter, prMsduInfo, prBssInfo); + + + //4 <5> Compose IEs in MSDU_INFO_T + + /* Append IE */ + for (i = 0; i < sizeof(txAssocRespIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].pfnAppendIE) { + txAssocRespIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + //4 <6> Enqueue the frame to send this (Re)Association request frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ +#endif /* CFG_SUPPORT_AAA */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c new file mode 100755 index 000000000000..9938ebc09823 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c @@ -0,0 +1,1350 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/auth.c#1 $ +*/ + +/*! \file "auth.c" + \brief This file includes the authentication-related functions. + + This file includes the authentication-related functions. +*/ + + + +/* +** $Log: auth.c $ + * + * 02 13 2012 cp.wu + * NULL + * show error message only instead of raise assertion when + * received authentication frame is carrying illegal parameters. + * + * 11 09 2011 yuche.tsai + * NULL + * Fix a network index & station record index issue when TX deauth frame. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 yuche.tsai + * NULL + * Fix coding error. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000796] [Volunteer Patch][MT6620][Driver] Add BC deauth frame TX feature. + * BC deauth support. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * 1. Fix Service Disocvery Logical issue. + * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 21 2011 terry.wu + * [WCXRP00000381] [MT6620 Wi-Fi][Driver] Kernel panic when replying unaccept Auth in AP mode + * In AP mode, use STA_REC_INDEX_NOT_FOUND(0xFE) instead of StaRec index when replying an unaccept Auth frame. + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update authSendDeauthFrame() for correct the value of eNetTypeIndex in MSDU_INFO_T + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Check Net is active before sending Deauth frame. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Fix compile warning + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add debug message for abnormal authentication frame from AP + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Fix the Debug Label + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update the authComposeAuthFrameHeader() + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the send deauth frame function + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Integrate send Auth with TXM + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +APPEND_IE_ENTRY_T txAuthIETable[] = { + { (ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), authAddIEChallengeText } +}; + +HANDLE_IE_ENTRY_T rxAuthIETable[] = { + { ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText } +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Authentication frame header and fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2AuthAlgNum Authentication Algorithm Number +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[in] u2StatusCode Status Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +authComposeAuthFrameHeaderAndFF ( + IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], + IN UINT_16 u2AuthAlgNum, + IN UINT_16 u2TransactionSeqNum, + IN UINT_16 u2StatusCode + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2FrameCtrl; + + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T)pucBuffer; + + //4 <1> Compose the frame header of the Authentication frame. + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_AUTH; + + /* If this frame is the third frame in the shared key authentication + * sequence, it shall be encrypted. + */ + if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && + (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) { + + u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; /* HW will also detect this bit for applying encryption */ + } + + //WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); + prAuthFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress); + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + break; + + default: + ASSERT(0); + } + + /* Clear the SEQ/FRAG_NO field. */ + prAuthFrame->u2SeqCtrl = 0; + + + //4 <2> Compose the frame body's fixed field part of the Authentication frame. + /* Fill the Authentication Algorithm Number field. */ + //WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); + prAuthFrame->u2AuthAlgNum = u2AuthAlgNum; // NOTE(Kevin): Optimized for ARM + + /* Fill the Authentication Transaction Sequence Number field. */ + //WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, u2TransactionSeqNum); + prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum; // NOTE(Kevin): Optimized for ARM + + /* Fill the Status Code field. */ + //WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); + prAuthFrame->u2StatusCode = u2StatusCode; // NOTE(Kevin): Optimized for ARM + + return; +} /* end of authComposeAuthFrameHeaderAndFF() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will append Challenge Text IE to the Authentication frame +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +authAddIEChallengeText ( + IN P_ADAPTER_T prAdapter, + IN OUT P_MSDU_INFO_T prMsduInfo + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if(!prStaRec) { + return; + } + + ASSERT(prStaRec); + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T)prMsduInfo->prPacket; + + WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) + + /* Only consider SEQ_3 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && + (prStaRec->prChallengeText != NULL)) { + + COPY_IE(((UINT_32)(prMsduInfo->prPacket) + prMsduInfo->u2FrameLength), + (prStaRec->prChallengeText)); + + prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText); + } + + return; + +} /* end of authAddIEChallengeText() */ + + +#if !CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_16 u2TransactionSeqNum + ) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_32 i; + + + DBGLOG(SAA, LOUD, ("Send Auth Frame\n")); + + ASSERT(prStaRec); + + //4 <1> Allocate a PKT_INFO_T for Authentication Frame + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable)/sizeof(APPEND_IE_ENTRY_T); i++) { + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SAA, WARN, ("No PKT_INFO_T for sending Auth Frame.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec->aucMacAddr, + prBssInfo->aucOwnMacAddr, + prStaRec->ucAuthAlgNum, + u2TransactionSeqNum, + STATUS_CODE_RESERVED); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + + //4 <3> Update information of MSDU_INFO_T + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Compose IEs in MSDU_INFO_T + for (i = 0; i < sizeof(txAuthIETable)/sizeof(APPEND_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) { + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + //4 <6> Inform TXM to send this Authentication frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#else + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_SW_RFB_T prFalseAuthSwRfb, + IN UINT_16 u2TransactionSeqNum, + IN UINT_16 u2StatusCode + ) +{ + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + /*get from input parameter*/ + //ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_16 ucAuthAlgNum; + UINT_32 i; + + + DBGLOG(SAA, LOUD, ("Send Auth Frame %d, Status Code = %d\n", + u2TransactionSeqNum, u2StatusCode)); + + //4 <1> Allocate a PKT_INFO_T for Authentication Frame + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable)/sizeof(APPEND_IE_ENTRY_T); i++) { + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SAA, WARN, ("No PKT_INFO_T for sending Auth Frame.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. + if (prStaRec) { + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucReceiveAddr = prStaRec->aucMacAddr; + + ucAuthAlgNum = prStaRec->ucAuthAlgNum; + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + pfTxDoneHandler = saaFsmRunEventTxDone; + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + pfTxDoneHandler = aaaFsmRunEventTxDone; + break; + } + + } + else { /* For Error Status Code */ + P_WLAN_AUTH_FRAME_T prFalseAuthFrame; + + + ASSERT(prFalseAuthSwRfb); + prFalseAuthFrame = (P_WLAN_AUTH_FRAME_T)prFalseAuthSwRfb->pvHeader; + + ASSERT(u2StatusCode != STATUS_CODE_SUCCESSFUL); + + pucTransmitAddr = prFalseAuthFrame->aucDestAddr; + + pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; + + ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; + + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, + pucTransmitAddr, + ucAuthAlgNum, + u2TransactionSeqNum, + u2StatusCode); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + + //4 <3> Update information of MSDU_INFO_T + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + if(prStaRec) { + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + } + else { + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; //false Auth frame + } + prMsduInfo->ucNetworkType = (UINT_8)eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Compose IEs in MSDU_INFO_T + for (i = 0; i < sizeof(txAuthIETable)/sizeof(APPEND_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) { + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + //4 <6> Inform TXM to send this Authentication frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#endif /* CFG_SUPPORT_AAA */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX Authentication frame for SAA/AAA event +* handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authCheckTxAuthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_16 u2TransactionSeqNum + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + UINT_16 u2TxAuthAlgNum; + UINT_16 u2TxTransactionSeqNum; + + + ASSERT(prMsduInfo); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T)(prMsduInfo->prPacket); + ASSERT(prAuthFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + //WLAN_GET_FIELD_16(&prAuthFrame->u2FrameCtrl, &u2TxFrameCtrl) + u2TxFrameCtrl = prAuthFrame->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (u2TxFrameCtrl != MAC_FRAME_AUTH) { + return WLAN_STATUS_FAILURE; + } + + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2TxAuthAlgNum) + u2TxAuthAlgNum = prAuthFrame->u2AuthAlgNum; // NOTE(Kevin): Optimized for ARM + if (u2TxAuthAlgNum != (UINT_16)(prStaRec->ucAuthAlgNum)) { + return WLAN_STATUS_FAILURE; + } + + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TxTransactionSeqNum) + u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; // NOTE(Kevin): Optimized for ARM + if (u2TxTransactionSeqNum != u2TransactionSeqNum) { + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckTxAuthFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Auth Frame's Transaction Sequence +* Number before delivering it to the corresponding SAA or AAA Module. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain authentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authCheckRxAuthFrameTransSeq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxTransactionSeqNum; + + + ASSERT(prSwRfb); + + //4 <1> locate the Authentication Frame. + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Header of Authentication Frame. + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_SUCCESS; + } + + //4 <3> Parse the Fixed Fields of Authentication Frame Body. + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; // NOTE(Kevin): Optimized for ARM + + switch (u2RxTransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + break; + + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); +#endif /* CFG_SUPPORT_AAA */ + break; + + default: + DBGLOG(SAA, WARN, ("Strange Authentication Packet: Auth Trans Seq No = %d, Error Status Code = %d\n", + u2RxTransactionSeqNum, prAuthFrame->u2StatusCode)); + break; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameTransSeq() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming Authentication Frame and take +* the status code out. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authCheckRxAuthFrameStatus ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_16 u2TransactionSeqNum, + OUT PUINT_16 pu2StatusCode + ) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxAuthAlgNum; + UINT_16 u2RxTransactionSeqNum; + //UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM + + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + //4 <1> locate the Authentication Frame. + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Fixed Fields of Authentication Frame Body. + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2RxAuthAlgNum); + u2RxAuthAlgNum = prAuthFrame->u2AuthAlgNum; // NOTE(Kevin): Optimized for ARM + if (u2RxAuthAlgNum != (UINT_16)prStaRec->ucAuthAlgNum) { + DBGLOG(SAA, LOUD, ("Discard Auth frame with auth type = %d, current = %d\n", + u2RxAuthAlgNum, prStaRec->ucAuthAlgNum)); + return WLAN_STATUS_FAILURE; + } + + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; // NOTE(Kevin): Optimized for ARM + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, LOUD, ("Discard Auth frame with Transaction Seq No = %d\n", + u2RxTransactionSeqNum)); + return WLAN_STATUS_FAILURE; + } + + //4 <3> Get the Status code + //WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); + //*pu2StatusCode = u2RxStatusCode; + *pu2StatusCode = prAuthFrame->u2StatusCode; // NOTE(Kevin): Optimized for ARM + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameStatus() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Challenge Text IE from the Authentication frame +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] prIEHdr Pointer to start address of IE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +authHandleIEChallengeText ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + P_IE_HDR_T prIEHdr + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + + ASSERT(prSwRfb); + ASSERT(prIEHdr); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(!prStaRec) { + return; + } + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T)prSwRfb->pvHeader; + + //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; // NOTE(Kevin): Optimized for ARM + + /* Only consider SEQ_2 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) { + + /* Free previous allocated TCM memory */ + if (prStaRec->prChallengeText) { + ASSERT(0); + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T)NULL; + } + + if ( ( prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)) ) == NULL) { + return; + } + + /* Save the Challenge Text from Auth Seq 2 Frame, before sending Auth Seq 3 Frame */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authProcessRxAuth2_Auth4Frame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + PUINT_8 pucIEsBuffer; + UINT_16 u2IEsLen; + UINT_16 u2Offset; + UINT_8 ucIEID; + UINT_32 i; + + + ASSERT(prSwRfb); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + pucIEsBuffer = &prAuthFrame->aucInfoElem[0]; + u2IEsLen = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + + IE_FOR_EACH(pucIEsBuffer, u2IEsLen, u2Offset) { + ucIEID = IE_ID(pucIEsBuffer); + + for (i = 0; i < (sizeof(rxAuthIETable) / sizeof(HANDLE_IE_ENTRY_T)); i++) { + + if (ucIEID == rxAuthIETable[i].ucElemID) { + rxAuthIETable[i].pfnHandleIE(prAdapter, prSwRfb, (P_IE_HDR_T)pucIEsBuffer); + } + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Deauthentication frame +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2StatusCode Status Code +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +authComposeDeauthFrameHeaderAndFF ( + IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], + IN UINT_8 aucBssid[], + IN UINT_16 u2ReasonCode + ) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + ASSERT(aucBssid); + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T)pucBuffer; + + //4 <1> Compose the frame header of the Deauthentication frame. + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DEAUTH; + + //WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); + prDeauthFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDeauthFrame->u2SeqCtrl = 0; + + //4 <2> Compose the frame body's fixed field part of the Authentication frame. + /* Fill the Status Code field. */ + //WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); + prDeauthFrame->u2ReasonCode = u2ReasonCode; // NOTE(Kevin): Optimized for ARM + + return; +} /* end of authComposeDeauthFrameHeaderAndFF() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Deauthenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. +* @param[in] u2ReasonCode A reason code to indicate why to leave BSS. +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +* @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendDeauthFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, + IN UINT_16 u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ) +{ + P_WLAN_MAC_HEADER_A4_T prWlanMacHeader = NULL; + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + PUINT_8 pucBssid = NULL; + + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2RxFrameCtrl; + P_BSS_INFO_T prBssInfo; + + P_DEAUTH_INFO_T prDeauthInfo; + OS_SYSTIME rCurrentTime; + INT_32 i4NewEntryIndex, i; + UINT_8 ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucBMC[] = BC_MAC_ADDR; +#endif + + /* NOTE(Kevin): The best way to reply the Deauth is according to the incoming data + * frame + */ + //4 <1> Find the Receiver Address first. + if (prClassErrSwRfb) { + BOOLEAN fgIsAbleToSendDeauth = FALSE; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_A4_T) prClassErrSwRfb->pvHeader; + + //WLAN_GET_FIELD_16(&prWlanMacHeader->u2FrameCtrl, &u2RxFrameCtrl); + u2RxFrameCtrl = prWlanMacHeader->u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* TODO(Kevin): Currently we won't send Deauth for IBSS node. How about DLS ? */ + if ((prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) == 0) { + return WLAN_STATUS_FAILURE; + } + + /* Check if corresponding BSS is able to send Deauth */ + for (i = NETWORK_TYPE_AIS_INDEX; i < NETWORK_TYPE_INDEX_NUM; i++) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[i]); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR(prWlanMacHeader->aucAddr1, prBssInfo->aucOwnMacAddr))) { + { + fgIsAbleToSendDeauth = TRUE; + eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T)i; + break; + } + } + } + + if (!fgIsAbleToSendDeauth) { + return WLAN_STATUS_FAILURE; + } + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + + } + else if (prStaRec) { + + pucReceiveAddr = prStaRec->aucMacAddr; + } + else { +#if CFG_ENABLE_WIFI_DIRECT + pucReceiveAddr = aucBMC; +#else + return WLAN_STATUS_FAILURE; +#endif + } + + //4 <2> Check if already send a Deauth frame in MIN_DEAUTH_INTERVAL_MSEC + GET_CURRENT_SYSTIME(&rCurrentTime); + + i4NewEntryIndex = -1; + for (i = 0; i < MAX_DEAUTH_INFO_COUNT; i++) { + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i]); + + + /* For continuously sending Deauth frame, the minimum interval is + * MIN_DEAUTH_INTERVAL_MSEC. + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prDeauthInfo->rLastSendTime, + MSEC_TO_SYSTIME(MIN_DEAUTH_INTERVAL_MSEC))) { + + i4NewEntryIndex = i; + } + else if (EQUAL_MAC_ADDR(pucReceiveAddr, prDeauthInfo->aucRxAddr) && + (!pfTxDoneHandler)) { + + return WLAN_STATUS_FAILURE; + } + } + + //4 <3> Update information. + if (i4NewEntryIndex > 0) { + + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i4NewEntryIndex]); + + COPY_MAC_ADDR(prDeauthInfo->aucRxAddr, pucReceiveAddr); + prDeauthInfo->rLastSendTime = rCurrentTime; + } + else { + /* NOTE(Kevin): for the case of AP mode, we may encounter this case + * if deauth all the associated clients. + */ + DBGLOG(SAA, WARN, ("No unused DEAUTH_INFO_T !\n")); + } + + //4 <4> Allocate a PKT_INFO_T for Deauthentication Frame + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SAA, WARN, ("No PKT_INFO_T for sending Deauth Request.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <5> Find the Transmitter Address and BSSID. + if (prClassErrSwRfb) { + + /* The TA of Deauth is the A1 of RX frame */ + pucTransmitAddr = prWlanMacHeader->aucAddr1; + + switch (prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + + case MASK_FC_FROM_DS: + /* The BSSID of Deauth is the A2 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + case MASK_FC_TO_DS: + /* The BSSID of Deauth is the A1 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr1; + break; + + case MASK_TO_DS_FROM_DS: + /* TODO(Kevin): Consider BOW, now we set the BSSID of Deauth + * to the A2 of RX frame for temporary solution. + */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + /* No Default */ + } + + } + else if (prStaRec) { + eNetTypeIndex = prStaRec->ucNetTypeIndex; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + } +#if CFG_ENABLE_WIFI_DIRECT + else { + if (prAdapter->fgIsP2PRegistered) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + } + else { + return WLAN_STATUS_FAILURE; + } + } + +#endif + + //4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, + pucTransmitAddr, + pucBssid, + u2ReasonCode); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T)(PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, ("authSendDeauthFrame with protection\n")); + } +#endif + + //4 <7> Update information of MSDU_INFO_T + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = ((prStaRec == NULL)?ucStaRecIdx:prStaRec->ucIndex); + prMsduInfo->ucNetworkType = (UINT_8)eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <8> Inform TXM to send this Deauthentication frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendDeauthFrame() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Deauthentication frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authProcessRxDeauthFrame ( + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucBSSID[], + OUT PUINT_16 pu2ReasonCode + ) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2RxReasonCode; + + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + //4 <1> locate the Deauthentication Frame. + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Parse the Header of Deauthentication Frame. +#if 0 // Kevin: Seems redundant + WLAN_GET_FIELD_16(&prDeauthFrame->u2FrameCtrl, &u2RxFrameCtrl) + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (u2RxFrameCtrl != MAC_FRAME_DEAUTH) { + return WLAN_STATUS_FAILURE; + } +#endif + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Deauth Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDeauthFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, ("Ignore Deauth Frame from other BSS ["MACSTR"]\n", + MAC2STR(prDeauthFrame->aucSrcAddr))); + return WLAN_STATUS_FAILURE; + } + + //4 <3> Parse the Fixed Fields of Deauthentication Frame Body. + WLAN_GET_FIELD_16(&prDeauthFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxDeauthFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucExpectedBSSID Given Expected BSSID. +* @param[in] u2ExpectedAuthAlgNum Given Expected Authentication Algorithm Number +* @param[in] u2ExpectedTransSeqNum Given Expected Transaction Sequence Number. +* @param[out] pu2ReturnStatusCode Return Status Code. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +* @retval WLAN_STATUS_FAILURE The frame we will ignore. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authProcessRxAuth1Frame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, + OUT PUINT_16 pu2ReturnStatusCode + ) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + + ASSERT(prSwRfb); + ASSERT(aucExpectedBSSID); + ASSERT(pu2ReturnStatusCode); + + //4 <1> locate the Authentication Frame. + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + //4 <2> Check the BSSID + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) { + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + } + + //4 <3> Parse the Fixed Fields of Authentication Frame Body. + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) { + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + } + + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) { + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + } + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c new file mode 100755 index 000000000000..263f18b88eb7 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c @@ -0,0 +1,2776 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#3 $ +*/ + +/*! \file "bss.c" + \brief This file contains the functions for creating BSS(AP)/IBSS(AdHoc). + + This file contains the functions for BSS(AP)/IBSS(AdHoc). We may create a BSS/IBSS + network, or merge with exist IBSS network and sending Beacon Frame or reply + the Probe Response Frame for received Probe Request Frame. +*/ + + + +/* +** $Log: bss.c $ +** +** 08 29 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 14 2012 chinglan.wang + * NULL + * Fix the losing of the HT IE in assoc request.. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 08 2012 yuche.tsai + * NULL + * Fix FW assert when start Hot-Spot. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 20 2012 chinglan.wang + * 03 02 2012 terry.wu + * NULL + * Fix the WPA-PSK TKIP and WPA2-PSK AES security mode bug. + * + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 15 2012 yuche.tsai + * NULL + * Fix wrong basic rate issue. + * + * 01 13 2012 yuche.tsai + * NULL + * WiFi Hot Spot Tethering for ICS ALPHA testing version. + * + * 11 03 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Always set short slot time to TRUE initially in AP mode + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 29 2011 eddie.chen + * [WCXRP00000608] [MT6620 Wi-Fi][DRV] Change wmm parameters in beacon + * Change wmm parameters in beacon. + * + * 03 29 2011 yuche.tsai + * [WCXRP00000607] [Volunteer Patch][MT6620][Driver] Coding Style Fix for klocwork scan. + * Fix klocwork issue. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 11 2011 chinglan.wang + * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. + * . + * + * 03 03 2011 george.huang + * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated + * . + * + * 03 03 2011 george.huang + * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated + * modify to handle if beacon MSDU been released when BSS deactivated + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Chnage GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 12 2011 yuche.tsai + * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. + * bss should create station record type according to callers input. + * + * 02 11 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * In p2p link function, check networktype before calling p2p function. + * + * 02 11 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Modify p2p link function to avoid assert. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 25 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Fix the compile error in windows. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 24 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * .Fix typo and missing entry + * + * 12 30 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Fix prBssInfo->aucCWminLog to prBssInfo->aucCWminLogForBcast + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 16 2010 yuche.tsai + * NULL + * Before composing Beacon IE, assign network type index for msdu info, + * this information is needed by RLM module while composing some RLM related IE field. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Fix undefined pucDestAddr in bssUpdateBeaconContent() + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 26 2010 yuche.tsai + * + * Add support to RX probe response for P2P. + * + * 07 20 2010 cp.wu + * + * 1) bugfix: do not stop timer for join after switched into normal_tr state, for providing chance for DHCP handshasking + * 2) modify rsnPerformPolicySelection() invoking + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error while enable WIFI_DIRECT support. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct when ADHOC support is turned on. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fix compilation error when WIFI_DIRECT is turned on + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update bssProcessProbeRequest() to avoid redundant SSID IE {0,0} for IOT. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Use TX MGMT Frame API for sending PS NULL frame to avoid the TX Burst Mechanism in TX FW Frame API + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Seperate Beacon and ProbeResp IE array + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed the use of compiling flag MQM_WMM_PARSING + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 20 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Fix restart Beacon Timeout Func after connection diagnosis + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * adding the wpa-none for ibss beacon. + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the protected bit at cap info for ad-hoc. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename the CFG flags + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Update outgoing beacon's TX data rate + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add DTIM count update while TX Beacon + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify code due to define - BAND_24G and specific BSS_INFO_T was changed + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +APPEND_VAR_IE_ENTRY_T txBcnIETable[] = { + { (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE } /* 50 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE } /* 42 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE } /* 45 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE } /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE } /* 74 */ +#endif + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE } /* 127 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE } /* 221 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE } /* 221 */ +#if CFG_ENABLE_WIFI_DIRECT + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE } /* 221 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE } /* 48 */ +#if 0 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + ,{ 0, p2pFuncCalculateExtra_IELenForBeacon, p2pFuncGenerateExtra_IEForBeacon } /* 221 */ +#else + ,{ 0, p2pFuncCalculateP2p_IELenForBeacon, p2pFuncGenerateP2p_IEForBeacon } /* 221 */ + ,{ 0, p2pFuncCalculateWSC_IELenForBeacon, p2pFuncGenerateWSC_IEForBeacon } /* 221 */ +#endif +#endif /* CFG_ENABLE_WIFI_DIRECT */ +}; + + +APPEND_VAR_IE_ENTRY_T txProbRspIETable[] = { + { (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE } /* 50 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE } /* 42 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE } /* 45 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE } /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE } /* 48 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE } /* 74 */ +#endif + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE } /* 127 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE } /* 221 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE } /* 221 */ +}; + +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create or reset a STA_RECORD_T by given BSS_DESC_T for +* Infrastructure or AdHoc Mode. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eStaType Assign STA Type for this STA_RECORD_T +* @param[in] eNetTypeIndex Assign Net Type Index for this STA_RECORD_T +* @param[in] prBssDesc Received Beacon/ProbeResp from this STA +* +* @retval Pointer to STA_RECORD_T +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_STA_RECORD_T prStaRec; + UINT_8 ucNonHTPhyTypeSet; + + + ASSERT(prBssDesc); + + //4 <1> Get a valid STA_RECORD_T + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, + prBssDesc->aucSrcAddr); + if (!prStaRec) { + + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) eNetTypeIndex); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + + if(!prStaRec) { + ASSERT(FALSE); + return NULL; + } + + ASSERT(prStaRec); + + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, we may also reset the ucJoinFailureCount to 0. + */ + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prBssDesc->aucSrcAddr); + } + + + //4 <2> Setup STA TYPE and NETWORK + prStaRec->eStaType = eStaType; + + prStaRec->ucNetTypeIndex = eNetTypeIndex; + + + //4 <3> Update information from BSS_DESC_T to current P_STA_RECORD_T + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + + if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED) || + (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) || + (prAdapter->prGlueInfo->u2WapiAssocInfoIESz))) { + DBGLOG(BSS, INFO, ("Ignore the HT Bit for TKIP as pairwise cipher configed!\n")); + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + } + + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; + + /* Check for Target BSS's non HT Phy Types */ + if (ucNonHTPhyTypeSet) { + + if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } + else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + else /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = TRUE; + } + else { + /* Use mandatory for 11N only BSS */ + ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); + + { + /* TODO(Kevin): which value should we set for 11n ? ERP ? */ + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = FALSE; + } + + /* Update non HT Desired Rate Set */ + { + P_CONNECTION_SETTINGS_T prConnSettings; + + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + } + + //4 <4> Update information from BSS_DESC_T to current P_STA_RECORD_T + if (IS_AP_STA(prStaRec)) { + /* do not need to parse IE for DTIM, + * which have been parsed before inserting into BSS_DESC_T + */ + if (prBssDesc->ucDTIMPeriod) { + prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + } + else { + prStaRec->ucDTIMPeriod = 0; // Means that TIM was not parsed. + } + } + + + //4 <5> Update default value + prStaRec->fgDiagnoseConnection = FALSE; + + + //4 <6> Update default value for other Modules + /* Determine fgIsWmmSupported and fgIsUapsdSupported in STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + return prStaRec; + +} /* end of bssCreateStaRecFromBssDesc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeNullFrame ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + IN P_STA_RECORD_T prStaRec + ) +{ + P_WLAN_MAC_HEADER_T prNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prNullFrame = (P_WLAN_MAC_HEADER_T)pucBuffer; + + //4 <1> Decide the Frame Control Field + u2FrameCtrl = MAC_FRAME_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) { + u2FrameCtrl |= MASK_FC_PWR_MGT; + } + } + else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } + else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } + else { + /* NOTE(Kevin): We won't send Null frame for IBSS */ + ASSERT(0); + return; + } + + //4 <2> Compose the Null frame + /* Fill the Frame Control field. */ + //WLAN_SET_FIELD_16(&prNullFrame->u2FrameCtrl, u2FrameCtrl); + prNullFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prNullFrame->u2SeqCtrl = 0; + + return; + +} /* end of bssComposeNullFrameHeader() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the QoS Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* @param[in] ucUP User Priority. +* @param[in] fgSetEOSP Set the EOSP bit. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeQoSNullFrame ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN BOOLEAN fgSetEOSP + ) +{ + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + UINT_16 u2QosControl; + + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T)pucBuffer; + + //4 <1> Decide the Frame Control Field + u2FrameCtrl = MAC_FRAME_QOS_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) { + u2FrameCtrl |= MASK_FC_PWR_MGT; + } + } + else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } + else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } + else { + /* NOTE(Kevin): We won't send QoS Null frame for IBSS */ + ASSERT(0); + return; + } + + //4 <2> Compose the QoS Null frame + /* Fill the Frame Control field. */ + //WLAN_SET_FIELD_16(&prQoSNullFrame->u2FrameCtrl, u2FrameCtrl); + prQoSNullFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prQoSNullFrame->u2SeqCtrl = 0; + + u2QosControl = (UINT_16)(ucUP & WMM_QC_UP_MASK); + + if (fgSetEOSP) { + u2QosControl |= WMM_QC_EOSP; + } + + //WLAN_SET_FIELD_16(&prQoSNullFrame->u2QosCtrl, u2QosControl); + prQoSNullFrame->u2QosCtrl = u2QosControl; // NOTE(Kevin): Optimized for ARM + + return; + +} /* end of bssComposeQoSNullFrameHeader() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Succe]ss. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendNullFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + + //4 <1> Allocate a PKT_INFO_T for Null Frame + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(BSS, WARN, ("No PKT_INFO_T for sending Null Frame.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose Null frame in MSDU_INfO_T. + bssComposeNullFrame(prAdapter, + (PUINT_8)((UINT_32)prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), + prStaRec); +#if 0 + //4 <3> Update information of MSDU_INFO_T + TXM_SET_DATA_PACKET( \ + /* STA_REC ptr */ prStaRec, \ + /* MSDU_INFO ptr */ prMsduInfo, \ + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), \ + /* MAC HDR length */ WLAN_MAC_HEADER_LEN, \ + /* PAYLOAD ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN), \ + /* PAYLOAD length */ 0, \ + /* Network Type Index */(UINT_8)prStaRec->ucNetTypeIndex, \ + /* TID */ 0 /* BE: AC1 */, \ + /* Flag 802.11 */ TRUE,\ + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, \ + /* Resource TC */ 0 /* Irrelevant */, \ + /* Flag 802.1x */ FALSE,\ + /* TX-done callback */ pfTxDoneHandler, \ + /* PS forwarding type*/ PS_FORWARDING_TYPE_NON_PS, \ + /* PS Session ID */ 0 /* Irrelevant */, \ + /* Flag fixed rate */ TRUE, \ + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, \ + /* Fixed-rate retry */ BSS_DEFAULT_CONN_TEST_NULL_FRAME_RETRY_LIMIT, \ + /* PAL LLH */ 0 /* Irrelevant */,\ + /* ACL SN */ 0 /* Irrelevant */,\ + /* Flag No Ack */ FALSE \ + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo,NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + //4 <4> Inform TXM to send this Null frame. + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + //4 <4> Inform TXM to send this Null frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendNullFrame() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the QoS Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendQoSNullFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + + //4 <1> Allocate a PKT_INFO_T for Null Frame + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(BSS, WARN, ("No PKT_INFO_T for sending Null Frame.\n")); + return WLAN_STATUS_RESOURCES; + } + + //4 <2> Compose Null frame in MSDU_INfO_T. + bssComposeQoSNullFrame(prAdapter, + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, + ucUP, + FALSE); +#if 0 + //4 <3> Update information of MSDU_INFO_T + TXM_SET_DATA_PACKET( \ + /* STA_REC ptr */ prStaRec, \ + /* MSDU_INFO ptr */ prMsduInfo, \ + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), \ + /* MAC HDR length */ WLAN_MAC_HEADER_QOS_LEN, \ + /* PAYLOAD ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN), \ + /* PAYLOAD length */ 0, \ + /* Network Type Index */(UINT_8)prStaRec->ucNetTypeIndex, \ + /* TID */ 0 /* BE: AC1 */, \ + /* Flag 802.11 */ TRUE,\ + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, \ + /* Resource TC */ 0 /* Irrelevant */, \ + /* Flag 802.1x */ FALSE,\ + /* TX-done callback */ pfTxDoneHandler, \ + /* PS forwarding type*/ PS_FORWARDING_TYPE_NON_PS, \ + /* PS Session ID */ 0 /* Irrelevant */, \ + /* Flag fixed rate */ TRUE, \ + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, \ + /* Fixed-rate retry */ TXM_DEFAULT_DATA_FRAME_RETRY_LIMIT, \ + /* PAL LLH */ 0 /* Irrelevant */,\ + /* ACL SN */ 0 /* Irrelevant */,\ + /* Flag No Ack */ FALSE \ + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo,NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + //4 <4> Inform TXM to send this Null frame. + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + //4 <4> Inform TXM to send this Null frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendQoSNullFrame() */ + + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate Information Elements of Extended +* Support Rate +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssGenerateExtSuppRate_IE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + PUINT_8 pucBuffer; + UINT_8 ucExtSupRatesLen; + + + ASSERT(prMsduInfo); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } + else { + ucExtSupRatesLen = 0; + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ELEM_MAX_LEN_SUP_RATES], + ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + + return; +} /* end of bssGenerateExtSuppRate_IE() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Beacon +* or Probe Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssBuildBeaconProbeRespFrameCommonIEs ( + IN P_MSDU_INFO_T prMsduInfo, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucDestAddr + ) +{ + PUINT_8 pucBuffer; + UINT_8 ucSupRatesLen; + + + ASSERT(prMsduInfo); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* Compose the frame body of the Probe Response frame. */ + //4 <1> Fill the SSID element. + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) { + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + + //4 <2> Fill the Supported Rates element. + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + } + else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + } + + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, + prBssInfo->aucAllSupportedRates, + ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + + //4 <3> Fill the DS Parameter Set element. + if (prBssInfo->eBand == BAND_2G4) { + DS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_DS_PARAM_SET; + DS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_DS_PARAMETER_SET; + DS_PARAM_IE(pucBuffer)->ucCurrChnl = prBssInfo->ucPrimaryChannel; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + + //4 <4> IBSS Parameter Set element, ID: 6 + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + IBSS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_IBSS_PARAM_SET; + IBSS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_IBSS_PARAMETER_SET; + WLAN_SET_FIELD_16(&(IBSS_PARAM_IE(pucBuffer)->u2ATIMWindow), prBssInfo->u2ATIMWindow); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + + //4 <5> TIM element, ID: 5 + if ((!pucDestAddr) && // For Beacon only. + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + +#if CFG_ENABLE_WIFI_DIRECT + /*no fgIsP2PRegistered protect*/ + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { +#if 0 + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_8 ucBitmapControl = 0; + UINT_32 u4N1, u4N2; + + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + // Clear existing value. + prP2pSpecificBssInfo->ucBitmapCtrl = 0; + kalMemZero(prP2pSpecificBssInfo->aucPartialVirtualBitmap, + sizeof(prP2pSpecificBssInfo->aucPartialVirtualBitmap)); + + + // IEEE 802.11 2007 - 7.3.2.6 + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucDTIMCount = prBssInfo->ucDTIMCount; + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + + // Setup DTIM Count for next TBTT. + if (prBssInfo->ucDTIMCount == 0) { + //3 *** pmQueryBufferedBCAST(); + } + + //3 *** pmQueryBufferedPSNode(); + /* TODO(Kevin): Call PM Module here to loop all STA_RECORD_Ts and it + * will call bssSetTIMBitmap to toggle the Bitmap. + */ + + // Set Virtual Bitmap for UCAST + u4N1 = (prP2pSpecificBssInfo->u2SmallestAID >> 4) << 1; // Find the largest even number. + u4N2 = prP2pSpecificBssInfo->u2LargestAID >> 3; // Find the smallest number. + + ASSERT(u4N2 >= u4N1); + + kalMemCopy(TIM_IE(pucBuffer)->aucPartialVirtualMap, + &prP2pSpecificBssInfo->aucPartialVirtualBitmap[u4N1], + ((u4N2 - u4N1) + 1)); + + // Set Virtual Bitmap for BMCAST + // BMC bit only indicated when DTIM count == 0. + if (prBssInfo->ucDTIMCount == 0) { + ucBitmapControl = prP2pSpecificBssInfo->ucBitmapCtrl; + } + TIM_IE(pucBuffer)->ucBitmapControl = ucBitmapControl | (UINT_8)u4N1; + + TIM_IE(pucBuffer)->ucLength = ((u4N2 - u4N1) + 4); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +#else + + // IEEE 802.11 2007 - 7.3.2.6 + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP)/*((u4N2 - u4N1) + 4)*/; // NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) + TIM_IE(pucBuffer)->ucDTIMCount = 0/*prBssInfo->ucDTIMCount*/; // will be overwrite by FW + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + TIM_IE(pucBuffer)->ucBitmapControl = 0/*ucBitmapControl | (UINT_8)u4N1*/; // will be overwrite by FW + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +#endif + + } + else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + + + + } + + return; +} /* end of bssBuildBeaconProbeRespFrameCommonIEs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Beacon/Probe Response frame header and +* its fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* @param[in] pucOwnMACAddress Given Our MAC Address. +* @param[in] pucBSSID Given BSSID of the BSS. +* @param[in] u2BeaconInterval Given Beacon Interval. +* @param[in] u2CapInfo Given Capability Info. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF ( + IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, + IN UINT_16 u2BeaconInterval, + IN UINT_16 u2CapInfo + ) +{ + P_WLAN_BEACON_FRAME_T prBcnProbRspFrame; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + UINT_16 u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + //DBGLOG(INIT, LOUD, ("\n")); + + + ASSERT(pucBuffer); + ASSERT(pucOwnMACAddress); + ASSERT(pucBSSID); + + prBcnProbRspFrame = (P_WLAN_BEACON_FRAME_T)pucBuffer; + + //4 <1> Compose the frame header of the Beacon /ProbeResp frame. + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } + else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + //WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; // NOTE(Kevin): Optimized for ARM + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + + //4 <2> Compose the frame body's common fixed field part of the Beacon /ProbeResp frame. + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + //WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, u2BeaconInterval); + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; // NOTE(Kevin): Optimized for ARM + + /* Fill the Capability Information field. */ + //WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); + prBcnProbRspFrame->u2CapInfo = u2CapInfo; // NOTE(Kevin): Optimized for ARM + + return; +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssUpdateBeaconContent ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_WLAN_BEACON_FRAME_T prBcnFrame; + UINT_32 i; + + DEBUGFUNC("bssUpdateBeaconContent"); + DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + //4 <1> Allocate a PKT_INFO_T for Beacon Frame + /* Allocate a MSDU_INFO_T */ + // For Beacon + prMsduInfo = prBssInfo->prBeacon; + + // beacon prMsduInfo will be NULLify once BSS deactivated, so skip if it is + if (prMsduInfo == NULL) { + return WLAN_STATUS_SUCCESS; + } + + //4 <2> Compose header + bssComposeBeaconProbeRespFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + NULL, + prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, + prBssInfo->u2CapInfo); + + + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + + prMsduInfo->ucNetworkType = eNetTypeIndex; + + //4 <3> Compose the frame body's Common IEs of the Beacon frame. + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, NULL); + + + //4 <4> Compose IEs in MSDU_INFO_T + + /* Append IE for Beacon */ + for (i = 0; i < sizeof(txBcnIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txBcnIETable[i].pfnAppendIE) { + txBcnIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + + prBcnFrame = (P_WLAN_BEACON_FRAME_T)prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + eNetTypeIndex, + prBssInfo->u2CapInfo, + (PUINT_8)prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); + + +} /* end of bssUpdateBeaconContent() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Beacon Frame(for BOW) or Probe Response Frame according to the given +* Destination Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* @param[in] pucDestAddr Pointer to the Destination Address to reply +* @param[in] u4ControlFlags Control flags for information on Probe Response. +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendBeaconProbeResponse ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, + IN UINT_32 u4ControlFlags + ) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedFixedIELen; + UINT_16 u2EstimatedExtraIELen; + P_APPEND_VAR_IE_ENTRY_T prIeArray = NULL; + UINT_32 u4IeArraySize = 0; + UINT_32 i; + + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + + if (!pucDestAddr) { // For Beacon + prIeArray = &txBcnIETable[0]; + u4IeArraySize = sizeof(txBcnIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); + } + else { + prIeArray = &txProbRspIETable[0]; + u4IeArraySize = sizeof(txProbRspIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); + } + + + //4 <1> Allocate a PKT_INFO_T for Beacon /Probe Response Frame + /* Allocate a MSDU_INFO_T */ + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Fields */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_MGMT_HEADER_LEN + \ + TIMESTAMP_FIELD_LEN + \ + BEACON_INTERVAL_FIELD_LEN + \ + CAP_INFO_FIELD_LEN + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_IBSS_PARAMETER_SET) + \ + (ELEM_HDR_LEN + (3 + MAX_LEN_TIM_PARTIAL_BMP)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < u4IeArraySize; i++) { + u2EstimatedFixedIELen = prIeArray[i].u2EstimatedFixedIELen; + + if (u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += u2EstimatedFixedIELen; + } + else { + ASSERT(prIeArray[i].pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += (UINT_16) + prIeArray[i].pfnCalculateVariableIELen(prAdapter, eNetTypeIndex, NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(BSS, WARN, ("No PKT_INFO_T for sending %s.\n", + ((!pucDestAddr)?"Beacon":"Probe Response"))); + return WLAN_STATUS_RESOURCES; + } + + + //4 <2> Compose Beacon/Probe Response frame header and fixed fields in MSDU_INfO_T. + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if(prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, + prAdapter->rWifiVar.aucDeviceAddress, + prAdapter->rWifiVar.aucDeviceAddress, + DOT11_BEACON_PERIOD_DEFAULT, + (prBssInfo->u2CapInfo & ~(CAP_INFO_ESS | CAP_INFO_IBSS))); + } + } + else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + bssComposeBeaconProbeRespFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, + prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, + prBssInfo->u2CapInfo); + } + + + //4 <3> Update information of MSDU_INFO_T + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = (UINT_8)eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + + //4 <4> Compose the frame body's Common IEs of the Beacon/ProbeResp frame. + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, pucDestAddr); + + + //4 <5> Compose IEs in MSDU_INFO_T + + /* Append IE */ + for (i = 0; i < u4IeArraySize; i++) { + if (prIeArray[i].pfnAppendIE) { + prIeArray[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + //4 <6> Inform TXM to send this Beacon /Probe Response frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendBeaconProbeResponse() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Probe Request Frame and then send +* back the corresponding Probe Response Frame if the specified conditions +* were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssProcessProbeRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + UINT_8 aucBCBSSID[] = BC_BSSID; + BOOLEAN fgIsBcBssid; + BOOLEAN fgReplyProbeResp; + UINT_32 u4CtrlFlagsForProbeResp = 0; + ENUM_BAND_T eBand; + UINT_8 ucHwChannelNum; + + + ASSERT(prSwRfb); + + //4 <1> Parse Probe Req and Get BSSID + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + if (EQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID)) { + fgIsBcBssid = TRUE; + } + else { + fgIsBcBssid = FALSE; + } + + + //4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) + for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) { + continue; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if ((!fgIsBcBssid) && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) { + continue; + } + + eBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + + if(prBssInfo->eBand != eBand) { + continue; + } + + if(prBssInfo->ucPrimaryChannel != ucHwChannelNum) { + continue; + } + + fgReplyProbeResp = FALSE; + + if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = aisValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex)) { + + fgReplyProbeResp = p2pFuncValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) { + + fgReplyProbeResp = bowValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); + } +#endif + + if (fgReplyProbeResp) { + if(nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM/2) ){ + /* Resource margin is enough */ + bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr, u4CtrlFlagsForProbeResp); + } + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ + + +#if 0 // NOTE(Kevin): condition check should move to P2P_FSM.c +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Probe Request Frame and then send +* back the corresponding Probe Response Frame if the specified conditions +* were matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssProcessProbeRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T)NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T)NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_8 aucBCBSSID[] = BC_BSSID; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + BOOLEAN fgReplyProbeResp; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgP2PTargetDeviceFound; + UINT_8 aucP2PWildcardSSID[] = P2P_WILDCARD_SSID; +#endif + + ASSERT(prSwRfb); + + //4 <1> Parse Probe Req and Get SSID IE ptr + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8)((UINT_32)prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + prIeSsid = (P_IE_SSID_T)NULL; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T)pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + // if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SUP_RATES) { + if (IE_LEN(pucIE) <= RATE_NUM) { + prIeSupportedRate = SUP_RATES_IE(pucIE); + } + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + +#if CFG_ENABLE_WIFI_DIRECT + // TODO: P2P IE & WCS IE parsing for P2P. + case ELEM_ID_P2P: + + break; +#endif + + /* no default */ + } + } /* end of IE_FOR_EACH */ + + //4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) + for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) { + continue; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (UNEQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID) && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) { + /* BSSID not Wildcard BSSID. */ + continue; + } + + fgReplyProbeResp = FALSE; + + if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + /* TODO(Kevin): Check if we are IBSS Master. */ + if (TRUE) { + + if (prIeSsid) { + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex) { + + // TODO(Kevin): Move following lines to p2p_fsm.c + + if ((prIeSsid) && + ((prIeSsid->ucLength == BC_SSID_LEN) || + (EQUAL_SSID(aucP2PWildcardSSID, + P2P_WILDCARD_SSID_LEN, + prIeSsid->aucSSID, + prIeSsid->ucLength)))) { +// if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prMgtHdr->aucSrcAddr, pucIE, u2IELength)) { + if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prSwRfb)) { + /* Extand channel request time & cancel scan request. */ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + // TODO: RX probe request may not caused by LISTEN state. + // TODO: It can be GO. + /* Generally speaking, cancel a non-exist scan request is fine. + * We can check P2P FSM here for only LISTEN state. + */ + + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + /* Abort JOIN process. */ + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + ASSERT(0); // Can't abort SCN FSM + continue; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prP2pFsmInfo->ucSeqNumOfScnMsg; + prScanCancelMsg->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->fgIsChannelExt = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prScanCancelMsg, + MSG_SEND_METHOD_BUF); + } + } + else { + /* 1. Probe Request without SSID. + * 2. Probe Request with SSID not Wildcard SSID & not P2P Wildcard SSID. + */ + continue; + } + +#if 0 // Frog + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_LISTEN) { + // P2P 2.4.1 - P2P Devices shall not respond to Probe Request frames which only contain 11b rates only. + if (prIeSupportedRate || prIeExtSupportedRate) { + UINT_16 u2OperationalRateSet, u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &u2OperationalRateSet, + &u2BSSBasicRateSet, /* Ignore any Basic Bit */ + &fgIsUnknownBssBasicRate); + + if (u2OperationalRateSet & ~RATE_SET_HR_DSSS) { + continue; + } + } + } + + // TODO: Check channel time before first check point to: + /* If Target device is selected: + * 1. Send XXXX request frame. + * else + * 1. Send Probe Response frame. + */ + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* TODO(Kevin): During PROVISION state, can we reply Probe Response ? */ + + /* TODO(Kevin): + * If we are GO, accept legacy client --> accept Wildcard SSID + * If we are in Listen State, accept only P2P Device --> check P2P IE and WPS IE + */ + if (TRUE /* We are GO */) { + if (prIeSsid) { + UINT_8 aucSSID[]=P2P_WILDCARD_SSID; + + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength) || + EQUAL_SSID(aucSSID, P2P_WILDCARD_SSID_LEN, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } + } +// else if (FALSE /* We are in Listen State */) { +// } + + /* TODO(Kevin): Check P2P IE and WPS IE */ + } +#endif + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* TODO(Kevin): TBD */ + } + } +#endif + else { + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + } + + if (fgReplyProbeResp) { + bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr); + } + + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to clear the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssClearClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo + ) +{ + P_LINK_T prStaRecOfClientList; + + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prPeerStaRec; + + LINK_FOR_EACH_ENTRY(prPeerStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + cnmStaRecChangeState(prAdapter, prPeerStaRec, STA_STATE_1); + } + + LINK_INITIALIZE(prStaRecOfClientList); + } + + return; +} /* end of bssClearClientList() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Add a STA_RECORD_T to the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssAddStaRecToClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec + ) +{ + P_LINK_T prStaRecOfClientList; + + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, WARN, ("Current Client List already contains that STA_RECORD_T["MACSTR"]\n", + MAC2STR(prStaRec->aucMacAddr))); + return; + } + } + } + + LINK_INSERT_TAIL(prStaRecOfClientList, &prStaRec->rLinkEntry); + + return; +} /* end of bssAddStaRecToClientList() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Remove a STA_RECORD_T from the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssRemoveStaRecFromClientList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec + ) +{ + P_LINK_T prStaRecOfClientList; + + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prStaRec->rLinkEntry); + + return; + } + } + } + + DBGLOG(BSS, INFO, ("Current Client List didn't contain that STA_RECORD_T["MACSTR"] before removing.\n", + MAC2STR(prStaRec->aucMacAddr))); + + return; +} /* end of bssRemoveStaRecFromClientList() */ +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to process Beacons from current Ad-Hoc network peers. +* We also process Beacons from other Ad-Hoc network during SCAN. If it has +* the same SSID and we'll decide to merge into it if it has a larger TSF. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 ucRCPI + ) +{ + P_STA_RECORD_T prStaRec = NULL; + + BOOLEAN fgIsCheckCapability = FALSE; + BOOLEAN fgIsCheckTSF = FALSE; + BOOLEAN fgIsGoingMerging = FALSE; + BOOLEAN fgIsSameBSSID; + + + ASSERT(prBssInfo); + ASSERT(prBssDesc); + + //4 <1> Process IBSS Beacon only after we create or merge with other IBSS. + if (!prBssInfo->fgIsBeaconActivated) { + return; + } + + //4 <2> Get the STA_RECORD_T of TA. + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_AIS_INDEX, + prBssDesc->aucSrcAddr); + + fgIsSameBSSID = UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID) ? FALSE : TRUE; + + + //4 <3> IBSS Merge Decision Flow for Processing Beacon. + if (fgIsSameBSSID) { + + /* Same BSSID: + * Case I. This is a new TA and it has decide to merged with us. + * a) If fgIsMerging == FALSE - we will send msg to notify AIS. + * b) If fgIsMerging == TRUE - already notify AIS. + * Case II. This is an old TA and we've already merged together. + */ + if (!prStaRec) { + + /* For Case I - Check this IBSS's capability first before adding this Sta Record. */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + + } + else { + + ASSERT((prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && + IS_ADHOC_STA(prStaRec)); + + if (prStaRec->ucStaState != STA_STATE_3) { + + if (!prStaRec->fgIsMerging) { + + /* For Case I - Check this IBSS's capability first before adding this Sta Record. */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + } + else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + } + else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + + } + } + else { + + /* Unequal BSSID: + * Case III. This is a new TA and we need to compare the TSF and get the winner. + * Case IV. This is an old TA and it merge into a new IBSS before we do the same thing. + * We need to compare the TSF to get the winner. + * Case V. This is an old TA and it restart a new IBSS. We also need to + * compare the TSF to get the winner. + */ + + /* For Case III, IV & V - We'll always check this new IBSS's capability first + * before merging into new IBSS. + */ + fgIsCheckCapability = TRUE; + + /* If check is passed, we need to perform TSF check to decide the major BSSID */ + fgIsCheckTSF = TRUE; + + /* For Case IV & V - We won't update rExpirationTime of Sta Record */ + } + + + //4 <7> Check this BSS_DESC_T's capability. + if (fgIsCheckCapability) { + BOOLEAN fgIsCapabilityMatched = FALSE; + + do { + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(BSS, LOUD, + ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Unsupported Phy.\n", + MAC2STR(prBssDesc->aucSrcAddr))); + + break; + } + + if (prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(BSS, LOUD, + ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Unknown Basic Rate.\n", + MAC2STR(prBssDesc->aucSrcAddr))); + + break; + } + + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + DBGLOG(BSS, LOUD, + ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Capability is not matched.\n", + MAC2STR(prBssDesc->aucSrcAddr))); + + break; + } + + fgIsCapabilityMatched = TRUE; + } + while (FALSE); + + if (!fgIsCapabilityMatched) { + + if (prStaRec) { + /* For Case II - We merge this STA_RECORD in RX Path. + * Case IV & V - They change their BSSID after we merge with them. + */ + + DBGLOG(BSS, LOUD, + ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Capability is not matched.\n", + MAC2STR(prBssDesc->aucSrcAddr))); + } + + return; + } + + DBGLOG(BSS, LOUD, + ("IBSS MERGE: Peer MAC: "MACSTR" - Check capability was passed.\n", + MAC2STR(prBssDesc->aucSrcAddr))); + } + + + if (fgIsCheckTSF) { +#if CFG_SLT_SUPPORT + fgIsGoingMerging = TRUE; +#else + if (prBssDesc->fgIsLargerTSF) { + fgIsGoingMerging = TRUE; + } + else { + return; + } +#endif + } + + + if (fgIsGoingMerging) { + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + + + //4 <1> We will merge with to this BSS immediately. + prBssDesc->fgIsConnecting = TRUE; + prBssDesc->fgIsConnected = FALSE; + + //4 <2> Setup corresponding STA_RECORD_T + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + STA_TYPE_ADHOC_PEER, + NETWORK_TYPE_AIS_INDEX, + prBssDesc); + + if(!prStaRec) { + // no memory ? + return; + } + + prStaRec->fgIsMerging = TRUE; + + /* update RCPI */ + prStaRec->ucRCPI = ucRCPI; + + //4 <3> Send Merge Msg to CNM to obtain the channel privilege. + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_IBSS_PEER_FOUND_T)); + + if (!prAisIbssPeerFoundMsg) { + + ASSERT(0); // Can't send Merge Msg + return; + } + + prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; + prAisIbssPeerFoundMsg->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_AIS_INDEX; + prAisIbssPeerFoundMsg->prStaRec = prStaRec; + + /* Inform AIS to do STATE TRANSITION + * For Case I - If AIS in IBSS_ALONE, let it jump to NORMAL_TR after we know the new member. + * For Case III, IV - Now this new BSSID wins the TSF, follow it. + */ + if (fgIsSameBSSID) { + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; + } + else { +#if CFG_SLT_SUPPORT + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; +#else + prAisIbssPeerFoundMsg->fgIsMergeIn = (prBssDesc->fgIsLargerTSF) ? FALSE: TRUE; +#endif + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisIbssPeerFoundMsg, + MSG_SEND_METHOD_BUF); + + } + + return; +} /* end of ibssProcessMatchedBeacon() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the Capability for Ad-Hoc to decide if we are +* able to merge with(same capability). +* +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. +* @retval WLAN_STATUS_SUCCESS Pass the check of Capability. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +ibssCheckCapabilityForAdHocMode ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + + ASSERT(prBssDesc); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + do { + //4 <1> Check the BSS Basic Rate Set for current AdHoc Mode + if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11B) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_HR_DSSS)) { + break; + } + else if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11A) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_OFDM)) { + break; + } + + //4 <2> Check the Short Slot Time. +#if 0 // Do not check ShortSlotTime until Wi-Fi define such policy + if (prConnSettings->eAdHocMode == AD_HOC_MODE_11G) { + if (((prConnSettings->fgIsShortSlotTimeOptionEnable) && + !(prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) || + (!(prConnSettings->fgIsShortSlotTimeOptionEnable) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))) { + break; + } + } +#endif + + //4 <3> Check the ATIM window setting. + if (prBssDesc->u2ATIMWindow) { + DBGLOG(BSS, INFO, ("AdHoc PS was not supported(ATIM Window: %d)\n", + prBssDesc->u2ATIMWindow)); + break; + } + +#if CFG_RSN_MIGRATION + //4 <4> Check the Security setting. + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) { + break; + } +#endif + + rStatus = WLAN_STATUS_SUCCESS; + } + while (FALSE); + + return rStatus; + +} /* end of ibssCheckCapabilityForAdHocMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for IBSS Mode. +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +ibssInitForAdHoc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo + ) +{ + UINT_8 ucLowestBasicRateIndex; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + PUINT_16 pu2BSSID = (PUINT_16)&aucBSSID[0]; + UINT_32 i; + + + ASSERT(prBssInfo); + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_IBSS); + + + //4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); + + //4 <2> Setup BSSID + if (!prBssInfo->fgHoldSameBssidForIBSS) { + + for (i = 0; i < sizeof(aucBSSID)/sizeof(UINT_16); i++) { + pu2BSSID[i] = (UINT_16)(kalRandomNumber() & 0xFFFF); + } + + aucBSSID[0] &= ~0x01; // 7.1.3.3.3 - The individual/group bit of the address is set to 0. + aucBSSID[0] |= 0x02; // 7.1.3.3.3 - The universal/local bit of the address is set to 1. + + COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); + } + + + //4 <3> Setup Capability - Short Preamble + if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO)) ) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + prBssInfo->fgUseShortPreamble = TRUE; + } + else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + + + //4 <4> Setup Capability - Short Slot Time + // 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. + prBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + + + //4 <5> Compoase Capability + prBssInfo->u2CapInfo = CAP_INFO_IBSS; + + if (prBssInfo->fgIsProtection) { + prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; + } + + if (prBssInfo->fgIsShortPreambleAllowed) { + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } + + if (prBssInfo->fgUseShortSlotTime) { + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + + + //4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + + prBssInfo->ucHwDefaultFixedRateCode = + aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + + return; +} /* end of ibssInitForAdHoc() */ + +#endif /* CFG_SUPPORT_ADHOC */ + + +#if CFG_SUPPORT_AAA + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for AP Mode. +* +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssInitForAP ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN BOOLEAN fgIsRateUpdate + ) +{ + UINT_8 ucLowestBasicRateIndex; + + P_AC_QUE_PARMS_T prACQueParms; + + ENUM_WMM_ACI_T eAci; + + UINT_8 auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4/*BE*/, 4 /*BK*/, 3/*VO*/, 2/*VI*/}; + UINT_8 auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3}; + UINT_8 auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; + UINT_8 auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ + + UINT_8 auCWminLog2[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/}; + UINT_8 auCWmaxLog2[WMM_AC_INDEX_NUM] = { 7, 10, 4, 3}; + UINT_8 auAifs[WMM_AC_INDEX_NUM] = { 3, 7, 1, 1 }; + UINT_8 auTxop[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ + + DEBUGFUNC("bssInitForAP"); + DBGLOG(BSS, LOUD,("\n")); + + ASSERT(prBssInfo); + ASSERT((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || (prBssInfo->eCurrentOPMode == OP_MODE_BOW)); + +#if 0 + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = CONFIG_BW_20M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = CONFIG_BW_20M; +#endif + + + //4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + if (fgIsRateUpdate) { + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); + } + + //4 <2> Setup BSSID + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssInfo->aucOwnMacAddr); + + + //4 <3> Setup Capability - Short Preamble + if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO)) ) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + prBssInfo->fgUseShortPreamble = TRUE; + } + else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + + + //4 <4> Setup Capability - Short Slot Time + prBssInfo->fgUseShortSlotTime = TRUE; + + //4 <5> Compoase Capability + prBssInfo->u2CapInfo = CAP_INFO_ESS; + + if (prBssInfo->fgIsProtection) { + prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; + } + + if (prBssInfo->fgIsShortPreambleAllowed) { + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } + + if (prBssInfo->fgUseShortSlotTime) { + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + + + //4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + + prBssInfo->ucHwDefaultFixedRateCode = + aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + + + //4 <7> Fill the EDCA + + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){ + + prACQueParms[eAci].fgIsACMSet = FALSE; + prACQueParms[eAci].u2Aifsn = auAifsForBcast[eAci]; + prACQueParms[eAci].u2CWmin = BIT(auCWminLog2ForBcast[eAci])-1; + prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2ForBcast[eAci])-1; + prACQueParms[eAci].u2TxopLimit = auTxopForBcast[eAci]; + + prBssInfo->aucCWminLog2ForBcast[eAci] = auCWminLog2ForBcast[eAci] ; /* used to send WMM IE */ + prBssInfo->aucCWmaxLog2ForBcast[eAci] = auCWmaxLog2ForBcast[eAci] ; + + DBGLOG(BSS, INFO, ("Bcast: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci,prACQueParms[eAci].fgIsACMSet , + prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, + prACQueParms[eAci].u2CWmax, + prACQueParms[eAci].u2TxopLimit)); + + } + + prACQueParms = prBssInfo->arACQueParms; + + for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){ + + prACQueParms[eAci].fgIsACMSet = FALSE; + prACQueParms[eAci].u2Aifsn = auAifs[eAci]; + prACQueParms[eAci].u2CWmin = BIT(auCWminLog2[eAci])-1; + prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2[eAci])-1; + prACQueParms[eAci].u2TxopLimit = auTxop[eAci]; + + DBGLOG(BSS, INFO, ("eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci,prACQueParms[eAci].fgIsACMSet , + prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, + prACQueParms[eAci].u2CWmax, + prACQueParms[eAci].u2TxopLimit)); + } + + /* Note: Caller should update the EDCA setting to HW by nicQmUpdateWmmParms() it there is no AIS network */ + /* Note: In E2, only 4 HW queues. The the Edca parameters should be folow by AIS network */ + /* Note: In E3, 8 HW queues. the Wmm parameters should be updated to right queues according to BSS */ + + + return; +} /* end of bssInitForAP() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update DTIM Count +* +* @param[in] eNetTypeIndex Specify which network to update +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssUpdateDTIMCount ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + P_BSS_INFO_T prBssInfo; + + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + // Setup DTIM Count for next TBTT. + if (prBssInfo->ucDTIMCount > 0) { + prBssInfo->ucDTIMCount--; + } + else { + + ASSERT(prBssInfo->ucDTIMPeriod > 0); + + prBssInfo->ucDTIMCount = prBssInfo->ucDTIMPeriod - 1; + } + } + + return; +} /* end of bssUpdateDTIMIE() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to set the Virtual Bitmap in TIM Information Elements +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] u2AssocId The association id to set in Virtual Bitmap. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssSetTIMBitmap ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN UINT_16 u2AssocId + ) +{ + + ASSERT(prBssInfo); + + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Use Association ID == 0 for BMCAST indication */ + if (u2AssocId == 0) { + + prP2pSpecificBssInfo->ucBitmapCtrl |= (UINT_8)BIT(0); + } + else { + PUINT_8 pucPartialVirtualBitmap; + UINT_8 ucBitmapToSet; + + + pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; // (u2AssocId / 8) + ucBitmapToSet = (UINT_8) BIT((u2AssocId % 8)); + + if (*pucPartialVirtualBitmap & ucBitmapToSet) { + /* The virtual bitmap has been set */ + return; + } + + *pucPartialVirtualBitmap |= ucBitmapToSet; + + // Update u2SmallestAID and u2LargestAID + if ((u2AssocId < prP2pSpecificBssInfo->u2SmallestAID) || + (prP2pSpecificBssInfo->u2SmallestAID == 0)) { + prP2pSpecificBssInfo->u2SmallestAID = u2AssocId; + } + + if ((u2AssocId > prP2pSpecificBssInfo->u2LargestAID) || + (prP2pSpecificBssInfo->u2LargestAID == 0)) { + prP2pSpecificBssInfo->u2LargestAID = u2AssocId; + } + } + } + + return; +} /* end of bssSetTIMBitmap() */ +#endif + +#endif /* CFG_SUPPORT_AAA */ + + +VOID +bssCreateStaRecFromAuth ( + IN P_ADAPTER_T prAdapter + ) +{ + +} + + +VOID +bssUpdateStaRecFromAssocReq ( + IN P_ADAPTER_T prAdapter + ) +{ + +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c new file mode 100755 index 000000000000..1af871d96310 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c @@ -0,0 +1,775 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm.c#2 $ +*/ + +/*! \file "cnm.c" + \brief Module of Concurrent Network Management + + Module of Concurrent Network Management +*/ + + + +/* +** $Log: cnm.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Fix possible wrong message when P2P is unregistered + * + * 11 14 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Fix large network type index assert in FW issue. + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 01 2011 cm.chang + * [WCXRP00001077] [All Wi-Fi][Driver] Fix wrong preferred channel for AP and BOW + * Only check AIS channel for P2P and BOW + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Extension channel of some 5G AP will not follow regulation requirement + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 01 2011 cm.chang + * [WCXRP00000937] [MT6620 Wi-Fi][Driver][FW] cnm.c line #848 assert when doing monkey test + * Print message only in Linux platform for monkey testing + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Limit AIS to fixed channel same with BOW + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Check if P2P network index is Tethering AP + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 02 17 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * When P2P registried, invoke BOW deactivate function + * + * 01 12 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Provide function to decide if BSS can be activated or not + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 10 13 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when cmd buffer is not available + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Fix wrong message ID for channel grant to requester + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set 20/40M bandwidth of AP HT OP before association process + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 21 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support TCP/UDP/IP Checksum offload feature + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add a new function to send abort message + * + * 04 27 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * BMC mac address shall be ignored in basic config command + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support change of MAC address by host command + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * adding the wpa-none for ibss beacon. + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix bug for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 25 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * use the Rx0 dor event indicate. + * + * 02 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support partial part about cmd basic configuration + * + * Dec 10 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove conditional compiling FPGA_V5 + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function cnmFsmEventInit() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmInit ( + P_ADAPTER_T prAdapter + ) +{ + return; +} /* end of cnmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmUninit ( + P_ADAPTER_T prAdapter + ) +{ + return; +} /* end of cnmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before handle the message from other module, it need to obtain +* the Channel privilege from Channel Manager +* +* @param[in] prMsgHdr The message need to be handled. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmChMngrRequestPrivilege ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_CH_REQ_T prMsgChReq; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChReq = (P_MSG_CH_REQ_T) prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, ("ChReq: fail to get buf (net=%d, token=%d)\n", + prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID)); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, ("ChReq net=%d token=%d b=%d c=%d s=%d\n", + prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfSco)); + + prCmdBody->ucNetTypeIndex = prMsgChReq->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChReq->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ + prCmdBody->ucPrimaryChannel = prMsgChReq->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prMsgChReq->eRfSco; + prCmdBody->ucRfBand = (UINT_8) prMsgChReq->eRfBand; + prCmdBody->ucReqType = (UINT_8) prMsgChReq->eReqType; + prCmdBody->ucReserved = 0; + prCmdBody->u4MaxInterval= prMsgChReq->u4MaxInterval; + COPY_MAC_ADDR(prCmdBody->aucBSSID, prMsgChReq->aucBSSID); + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(CNM, ERROR, ("CNM: ChReq with wrong netIdx=%d\n\n", + prCmdBody->ucNetTypeIndex)); + } + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + + return; +} /* end of cnmChMngrRequestPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before deliver the message to other module, it need to release +* the Channel privilege to Channel Manager. +* +* @param[in] prMsgHdr The message need to be delivered +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmChMngrAbortPrivilege ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_CH_ABORT_T prMsgChAbort; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (P_MSG_CH_ABORT_T) prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, ("ChAbort: fail to get buf (net=%d, token=%d)\n", + prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID)); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, ("ChAbort net=%d token=%d\n", + prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID)); + + prCmdBody->ucNetTypeIndex = prMsgChAbort->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(CNM, ERROR, ("CNM: ChAbort with wrong netIdx=%d\n\n", + prCmdBody->ucNetTypeIndex)); + } + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + + return; +} /* end of cnmChMngrAbortPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmChMngrHandleChEvent ( + P_ADAPTER_T prAdapter, + P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_CH_PRIVILEGE_T prEventBody; + P_MSG_CH_GRANT_T prChResp; + + ASSERT(prAdapter); + ASSERT(prEvent); + + prEventBody = (P_EVENT_CH_PRIVILEGE_T) (prEvent->aucBuffer); + prChResp = (P_MSG_CH_GRANT_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_GRANT_T)); + ASSERT(prChResp); + + /* To do: exception handle */ + if (!prChResp) { + DBGLOG(CNM, ERROR, ("ChGrant: fail to get buf (net=%d, token=%d)\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID)); + + return; + } + + DBGLOG(CNM, INFO, ("ChGrant net=%d token=%d ch=%d sco=%d\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID, + prEventBody->ucPrimaryChannel, prEventBody->ucRfSco)); + + ASSERT(prEventBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + /* Decide message ID based on network and response status */ + if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prEventBody->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) { + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; + } +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucNetTypeIndex = prEventBody->ucNetTypeIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (ENUM_CHNL_EXT_T) prEventBody->ucRfSco; + prChResp->eRfBand = (ENUM_BAND_T) prEventBody->ucRfBand; + prChResp->eReqType = (ENUM_CH_REQ_TYPE_T) prEventBody->ucReqType; + prChResp->u4GrantInterval = prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prChResp, + MSG_SEND_METHOD_BUF); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked for P2P or BOW networks +* +* @param (none) +* +* @return TRUE: suggest to adopt the returned preferred channel +* FALSE: No suggestion. Caller should adopt its preference +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmPreferredChannel ( + P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prBand, + PUINT_8 pucPrimaryChannel, + P_ENUM_CHNL_EXT_T prBssSCO + ) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + *prBssSCO = prBssInfo->eBssSCO; + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: available channel is limited to return value +* FALSE: no limited +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmAisInfraChannelFixed ( + P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prBand, + PUINT_8 pucPrimaryChannel + ) +{ +#if CFG_ENABLE_WIFI_DIRECT ||(CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL) + P_BSS_INFO_T prBssInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + + ASSERT(prAdapter->fgIsP2PRegistered); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmAisInfraConnectNotify ( + P_ADAPTER_T prAdapter + ) +{ +#if CFG_ENABLE_BT_OVER_WIFI + P_BSS_INFO_T prAisBssInfo, prBowBssInfo; + + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prBowBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + if (RLM_NET_PARAM_VALID(prAisBssInfo) && RLM_NET_PARAM_VALID(prBowBssInfo)){ + if (prAisBssInfo->eBand != prBowBssInfo->eBand || + prAisBssInfo->ucPrimaryChannel != prBowBssInfo->ucPrimaryChannel) { + + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmAisIbssIsPermitted ( + P_ADAPTER_T prAdapter + ) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + return FALSE; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + return FALSE; + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmP2PIsPermitted ( + P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && + prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + return FALSE; + } + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmBowIsPermitted ( + P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && + prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + return FALSE; + } + +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + return FALSE; + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmBss40mBwPermitted ( + P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx + ) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + + /* Note: To support real-time decision instead of current activated-time, + * the STA roaming case shall be considered about synchronization + * problem. Another variable fgAssoc40mBwAllowed is added to + * represent HT capability when association + */ + for (i = 0; i < NETWORK_TYPE_INDEX_NUM; i++) { + if (i != (UINT_8) eNetTypeIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[i]; + + if (IS_BSS_ACTIVE(prBssInfo) && (prBssInfo->fg40mBwAllowed || + prBssInfo->fgAssoc40mBwAllowed)) { + return FALSE; + } + } + } + + return TRUE; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c new file mode 100755 index 000000000000..a1a50baf5382 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c @@ -0,0 +1,1292 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_mem.c#2 $ +*/ + +/*! \file "cnm_mem.c" + \brief This file contain the management function of packet buffers and + generic memory alloc/free functioin for mailbox message. + + A data packet has a fixed size of buffer, but a management + packet can be equipped with a variable size of buffer. +*/ + + + +/* +** $Log: cnm_mem.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 14 2012 wh.su + * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting + * Add code from 2.2 + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * initialize fgNeedResp. + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 11 25 2010 yuche.tsai + * NULL + * Update SLT Function for QoS Support and not be affected by fixed rate function. + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 10 13 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when cmd buffer is not available + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 05 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Fix correct structure size in cnmStaSendDeactivateCmd() + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * spin lock target revised + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change inner loop index from i to k. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support checking of duplicated buffer free + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Modified some MQM-related data structures (SN counter, TX/RX BA table) + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Added new TX/RX BA tables in STA_REC + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Notify MQM, TXM, and RXM upon disconnection . + * + * 04 26 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Call mqm, txm, rxm functions upon disconnection + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * * * * * * * * and will send Null frame to diagnose connection + * + * 04 09 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * [BORA00000644] WiFi phase 4 integration + * * Added per-TID SN cache in STA_REC + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * move the wlan table alloc / free to change state function. + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support power control + * + * 03 03 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Initialize StaRec->arStaWaitQueue + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add debug message when no available pkt buffer + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Fixed STA_REC initialization bug: prStaRec->au2CachedSeqCtrl[k] + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsWmmSupported in STA_RECORD_T. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsUapsdSupported in STA_RECORD_T + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * add support of Driver STA_RECORD_T activation + * + * 02 13 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added arTspecTable in STA_REC for TSPEC management + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable mgmt buffer debug by default + * + * 02 12 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added BUFFER_SOURCE_BCN + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h + * * * * * * * * * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem + * * * * * * * * * 3) use cnmMemAlloc() instead to allocate SRAM buffer + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * * * * * * MQM: BA handling + * * * * * * * TXM: Macros updates + * * * * * * * RXM: Macros/Duplicate Removal updates + * + * 12 24 2009 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support several data buffer banks. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * .For new FPGA memory size + * + * Dec 9 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed DBGPRINT + * + * Dec 9 2009 mtk02752 + * [BORA00000368] Integrate HIF part into BORA + * add cnmDataPktFree() for emulation loopback purpose + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix warning of null pointer + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add cnmGetStaRecByAddress() and add fgIsInUse flag in STA_RECORD_T + * + * Nov 23 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Assign ucBufferSource in function cnmMgtPktAlloc() + * + * Nov 23 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added packet redispatch function calls + * + * Nov 13 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * enable packet re-usable in current emulation driver + * + * Nov 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * 1. Add new function cnmGetStaRecByIndex() + * 2. Rename STA_REC_T to STA_RECORD_T + * + * Nov 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call cnmDataPktDispatch() in cnmPktFree() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove definition of pragma section code + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Oct 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 8 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID +cnmStaRecHandleEventPkt ( + P_ADAPTER_T prAdapter, + P_CMD_INFO_T prCmdInfo, + PUINT_8 pucEventBuf + ); + +static VOID +cnmStaSendUpdateCmd ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + BOOLEAN fgNeedResp + ); + +static VOID +cnmStaSendRemoveCmd ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +cnmMgtPktAlloc ( + P_ADAPTER_T prAdapter, + UINT_32 u4Length + ) +{ + P_MSDU_INFO_T prMsduInfo; + P_QUE_T prQueList; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + /* Get a free MSDU_INFO_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(prQueList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo) { + prMsduInfo->prPacket = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + prMsduInfo->eSrc = TX_PACKET_MGMT; + + if (prMsduInfo->prPacket == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = NULL; + } + } + +#if DBG + if (prMsduInfo == NULL) { + DBGLOG(MEM, WARN, ("\n")); + DBGLOG(MEM, WARN, ("MgtDesc#=%ld\n", prQueList->u4NumElem)); + +#if CFG_DBG_MGT_BUF + DBGLOG(MEM, WARN, ("rMgtBufInfo: alloc#=%ld, free#=%ld, null#=%ld\n", + prAdapter->rMgtBufInfo.u4AllocCount, + prAdapter->rMgtBufInfo.u4FreeCount, + prAdapter->rMgtBufInfo.u4AllocNullCount)); +#endif + + DBGLOG(MEM, WARN, ("\n")); + } +#endif + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmMgtPktFree ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_QUE_T prQueList; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + ASSERT(prMsduInfo->prPacket); + if (prMsduInfo->prPacket) { + cnmMemFree(prAdapter, prMsduInfo->prPacket); + prMsduInfo->prPacket = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to initial the MGMT/MSG memory pool. +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmMemInit ( + P_ADAPTER_T prAdapter + ) +{ + P_BUF_INFO_T prBufInfo; + + /* Initialize Management buffer pool */ + prBufInfo = &prAdapter->rMgtBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMgtBufInfo)); + prBufInfo->pucBuf = prAdapter->pucMgtBufCached; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = + (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + + /* Initialize Message buffer pool */ + prBufInfo = &prAdapter->rMsgBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMsgBufInfo)); + prBufInfo->pucBuf = &prAdapter->aucMsgBuf[0]; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = + (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + return; + +} /* end of cnmMemInit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate MGMT/MSG memory pool. +* +* \param[in] eRamType Target RAM type. +* TCM blk_sz= 16bytes, BUF blk_sz= 256bytes +* \param[in] u4Length Length of the buffer to allocate. +* +* \retval !NULL Pointer to the start address of allocated memory. +* \retval NULL Fail to allocat memory +*/ +/*----------------------------------------------------------------------------*/ +PVOID +cnmMemAlloc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_RAM_TYPE_T eRamType, + IN UINT_32 u4Length + ) +{ + P_BUF_INFO_T prBufInfo; + BUF_BITMAP rRequiredBitmap; + UINT_32 u4BlockNum; + UINT_32 i, u4BlkSzInPower; + PVOID pvMemory; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(u4Length); + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4Length += (MSG_BUF_BLOCK_SIZE - 1); + u4BlockNum = u4Length >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + else { + eRamType = RAM_TYPE_BUF; + + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlkSzInPower = MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4Length += (MGT_BUF_BLOCK_SIZE - 1); + u4BlockNum = u4Length >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocCount++; +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + if ((u4BlockNum > 0) && (u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS)) { + + /* Convert number of block into bit cluster */ + rRequiredBitmap = BITS(0, u4BlockNum-1); + + for (i = 0; i <= (MAX_NUM_OF_BUF_BLOCKS - u4BlockNum); i++) { + + /* Have available memory blocks */ + if ((prBufInfo->rFreeBlocksBitmap & rRequiredBitmap) + == rRequiredBitmap) { + + /* Clear corresponding bits of allocated memory blocks */ + prBufInfo->rFreeBlocksBitmap &= ~rRequiredBitmap; + + /* Store how many blocks be allocated */ + prBufInfo->aucAllocatedBlockNum[i] = (UINT_8) u4BlockNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? + SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + /* Return the start address of allocated memory */ + return (PVOID)(prBufInfo->pucBuf + (i << u4BlkSzInPower)); + + } + + rRequiredBitmap <<= 1; + } + } + +#ifdef LINUX + pvMemory = (PVOID)kalMemAlloc(u4Length, VIR_MEM_TYPE); +#else + pvMemory = (PVOID)NULL; +#endif + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; + + if (pvMemory) { + prAdapter->u4MemAllocDynamicCount++; + } +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return pvMemory; + +} /* end of cnmMemAlloc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release memory to MGT/MSG memory pool. +* +* \param pucMemory Start address of previous allocated memory +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmMemFree ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvMemory + ) +{ + P_BUF_INFO_T prBufInfo; + UINT_32 u4BlockIndex; + BUF_BITMAP rAllocatedBlocksBitmap; + ENUM_RAM_TYPE_T eRamType; + KAL_SPIN_LOCK_DECLARATION(); + + + ASSERT(prAdapter); + ASSERT(pvMemory); + if (!pvMemory) { + return; + } + + /* Judge it belongs to which RAM type */ + if ( ((UINT_32)pvMemory >= (UINT_32)&prAdapter->aucMsgBuf[0]) && + ((UINT_32)pvMemory <= (UINT_32)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE-1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((UINT_32)pvMemory - (UINT_32)prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } + else if ( ((UINT_32)pvMemory >= (UINT_32)prAdapter->pucMgtBufCached) && + ((UINT_32)pvMemory <= ((UINT_32)prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE -1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((UINT_32)pvMemory - (UINT_32)prBufInfo->pucBuf) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_BUF; + } + else { + #ifdef LINUX + /* For Linux, it is supported because size is not needed */ + kalMemFree(pvMemory, VIR_MEM_TYPE, 0); + #else + /* For Windows, it is not supported because of no size argument */ + ASSERT(0); + #endif + + #if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount++; + #endif + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4FreeCount++; +#endif + + /* Convert number of block into bit cluster */ + ASSERT(prBufInfo->aucAllocatedBlockNum[u4BlockIndex] > 0); + + rAllocatedBlocksBitmap = + BITS(0, prBufInfo->aucAllocatedBlockNum[u4BlockIndex] - 1); + rAllocatedBlocksBitmap <<= u4BlockIndex; + + /* Clear saved block count for this memory segment */ + prBufInfo->aucAllocatedBlockNum[u4BlockIndex] = 0; + + /* Set corresponding bit of released memory block */ + prBufInfo->rFreeBlocksBitmap |= rAllocatedBlocksBitmap; + + KAL_RELEASE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return; + +} /* end of cnmMemFree() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaRecInit ( + P_ADAPTER_T prAdapter + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + prStaRec->ucIndex = (UINT_8) i; + prStaRec->fgIsInUse = FALSE; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaRecUninit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse) { + cnmStaRecFree(prAdapter, prStaRec, FALSE); + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +cnmStaRecAlloc ( + P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i, k; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + /*---- Initialize STA_REC_T here ----*/ + kalMemZero(prStaRec, sizeof(STA_RECORD_T)); + prStaRec->ucIndex = (UINT_8) i; + prStaRec->ucNetTypeIndex = ucNetTypeIndex; + prStaRec->fgIsInUse = TRUE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) { + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + } + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) { + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + } + + /* Default enable TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = TRUE; + prStaRec->fgRxAmpduEn = TRUE; + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) { + QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]); + } + + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaRecFree ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + BOOLEAN fgSyncToChip + ) +{ + ASSERT(prAdapter); + ASSERT(prStaRec); + + /* To do: free related resources, e.g. timers, buffers, etc */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + prStaRec->fgTransmitKeyExist = FALSE; + prStaRec->fgSetPwrMgtBit = FALSE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + + if (fgSyncToChip) { + cnmStaSendRemoveCmd(prAdapter, prStaRec); + } + + prStaRec->fgIsInUse = FALSE; + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaFreeAllStaByNetType ( + P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + BOOLEAN fgSyncToChip + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex) { + + cnmStaRecFree(prAdapter, prStaRec, fgSyncToChip); + } + } /* end of for loop */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +cnmGetStaRecByIndex ( + P_ADAPTER_T prAdapter, + UINT_8 ucIndex + ) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prStaRec = (ucIndex < CFG_STA_REC_NUM) ? + &prAdapter->arStaRec[ucIndex] : NULL; + + if (prStaRec && prStaRec->fgIsInUse == FALSE) { + prStaRec = NULL; + } + + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get STA_RECORD_T by Peer MAC Address(Usually TA). +* +* @param[in] pucPeerMacAddr Given Peer MAC Address. +* +* @retval Pointer to STA_RECORD_T, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +cnmGetStaRecByAddress ( + P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + PUINT_8 pucPeerMacAddr + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + ASSERT(pucPeerMacAddr); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucNetTypeIndex == ucNetTypeIndex && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Reset the Status and Reason Code Field to 0 of all Station Records for +* the specified Network Type +* +* @param[in] eNetType Specify Network Type +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaRecResetStatus ( + P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + cnmStaFreeAllStaByNetType(prAdapter, eNetTypeIndex, FALSE); + +#if 0 + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse) { + if ((NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) && + IS_STA_IN_AIS(prStaRec->eStaType)) { + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + } + + /* TODO(Kevin): For P2P and BOW */ + } + } + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will change the ucStaState of STA_RECORD_T and also do +* event indication to HOST to sync the STA_RECORD_T in driver. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u4NewState New STATE to change. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmStaRecChangeState ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + UINT_8 ucNewState + ) +{ + BOOLEAN fgNeedResp; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* Do nothing when following state transitions happen, + * other 6 conditions should be sync to FW, including 1-->1, 3-->3 + */ + if ((ucNewState == STA_STATE_2 && prStaRec->ucStaState != STA_STATE_3) || + (ucNewState == STA_STATE_1 && prStaRec->ucStaState == STA_STATE_2)) { + prStaRec->ucStaState = ucNewState; + return; + } + + fgNeedResp = FALSE; + if (ucNewState == STA_STATE_3) { + secFsmEventStart(prAdapter, prStaRec); + if (ucNewState != prStaRec->ucStaState) { + fgNeedResp = TRUE; + } + } + else { + if (ucNewState != prStaRec->ucStaState && + prStaRec->ucStaState == STA_STATE_3) { + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + } + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, fgNeedResp); + +#if CFG_ENABLE_WIFI_DIRECT + /* To do: Confirm if it is invoked here or other location, but it should + * be invoked after state sync of STA_REC + * Update system operation parameters for AP mode + */ + if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) { + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } + } +#endif + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +cnmStaRecHandleEventPkt ( + P_ADAPTER_T prAdapter, + P_CMD_INFO_T prCmdInfo, + PUINT_8 pucEventBuf + ) +{ + P_EVENT_ACTIVATE_STA_REC_T prEventContent; + P_STA_RECORD_T prStaRec; + + prEventContent = (P_EVENT_ACTIVATE_STA_REC_T) pucEventBuf; + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventContent->ucStaRecIdx); + + if (prStaRec && prStaRec->ucStaState == STA_STATE_3 && + !kalMemCmp(&prStaRec->aucMacAddr[0], &prEventContent->aucMacAddr[0], + MAC_ADDR_LEN)) { + + qmActivateStaRec(prAdapter, prStaRec); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +cnmStaSendUpdateCmd ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec, + BOOLEAN fgNeedResp + ) +{ + P_CMD_UPDATE_STA_RECORD_T prCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* To do: come out a mechanism to limit one STA_REC sync once for AP mode + * to avoid buffer empty case when many STAs are associated + * simultaneously. + */ + + /* To do: how to avoid 2 times of allocated memory. Use Stack? + * One is here, the other is in wlanSendQueryCmd() + */ + prCmdContent = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(CMD_UPDATE_STA_RECORD_T)); + ASSERT(prCmdContent); + + /* To do: exception handle */ + if (!prCmdContent) { + return; + } + + prCmdContent->ucIndex = prStaRec->ucIndex; + prCmdContent->ucStaType = (UINT_8) prStaRec->eStaType; + kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], + MAC_ADDR_LEN); + prCmdContent->u2AssocId = prStaRec->u2AssocId; + prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; + prCmdContent->ucNetTypeIndex = prStaRec->ucNetTypeIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32; + prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; + prCmdContent->ucNeedResp = (UINT_8) fgNeedResp; + +#if !CFG_SLT_SUPPORT + if(prAdapter->rWifiVar.eRateSetting != FIXED_RATE_NONE) { + /* override rate configuration */ + nicUpdateRateParams(prAdapter, + prAdapter->rWifiVar.eRateSetting, + &(prCmdContent->ucDesiredPhyTypeSet), + &(prCmdContent->u2DesiredNonHTRateSet), + &(prCmdContent->u2BSSBasicRateSet), + &(prCmdContent->ucMcsSet), + &(prCmdContent->ucSupMcs32), + &(prCmdContent->u2HtCapInfo)); + } +#endif + + prCmdContent->ucIsQoS = prStaRec->fgIsQoS; + prCmdContent->ucIsUapsdSupported = prStaRec->fgIsUapsdSupported; + prCmdContent->ucStaState = prStaRec->ucStaState; + + prCmdContent->ucAmpduParam = prStaRec->ucAmpduParam; + prCmdContent->u2HtExtendedCap = prStaRec->u2HtExtendedCap; + prCmdContent->u4TxBeamformingCap = prStaRec->u4TxBeamformingCap; + prCmdContent->ucAselCap = prStaRec->ucAselCap; + prCmdContent->ucRCPI = prStaRec->ucRCPI; + + prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_UPDATE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + fgNeedResp, /* fgNeedResp */ + FALSE, /* fgIsOid */ + fgNeedResp? cnmStaRecHandleEventPkt : NULL, + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_UPDATE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdContent); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +cnmStaSendRemoveCmd ( + P_ADAPTER_T prAdapter, + P_STA_RECORD_T prStaRec + ) +{ + CMD_REMOVE_STA_RECORD_T rCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + rCmdContent.ucIndex = prStaRec->ucIndex; + kalMemCopy(&rCmdContent.aucMacAddr[0], &prStaRec->aucMacAddr[0], + MAC_ADDR_LEN); + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_REMOVE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_REMOVE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c new file mode 100755 index 000000000000..2e8a8d7fa1b8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c @@ -0,0 +1,531 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 $ +*/ + +/*! \file "cnm_timer.c" + \brief + +*/ + + + +/* +** $Log: cnm_timer.c $ + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support sleep notification to host + * + * 05 19 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some checking assertions + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Return timer token back to COS when entering wait off state + * + * 01 11 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning + * + * 01 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb + * + * 01 06 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix system time is 32KHz instead of 1ms + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Place rRootTimer.rNextExpiredSysTime = rExpiredSysTime; before set timer + * + * Oct 30 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * In cnmTimerInitialize(), just stop timer if it was already created. + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Move the external reference for Lint to precomp.h + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] rTimeout Time out interval from current time. +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +cnmTimerSetTimer ( + IN P_ADAPTER_T prAdapter, + IN OS_SYSTIME rTimeout + ) +{ + P_ROOT_TIMER prRootTimer; + BOOLEAN fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { + fgNeedWakeLock = TRUE; + + if (!prRootTimer->fgWakeLocked) { + KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = TRUE; + } + } + else { + fgNeedWakeLock = FALSE; + } + + return fgNeedWakeLock; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a root timer. +* +* \param[in] prAdapter +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROOT_TIMER prRootTimer; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to destroy a root timer. +* When WIFI is off, the token shall be returned back to system. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerDestroy ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROOT_TIMER prRootTimer; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] pfnFunc Pointer to the call back function. +* \param[in] u4Data Parameter for call back function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerInitTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN UINT_32 u4Data + ) +{ + ASSERT(prAdapter); + + ASSERT(prTimer); + +#if DBG + /* Note: NULL function pointer is permitted for HEM POWER */ + if (pfFunc == NULL) { + DBGLOG(CNM, WARN, ("Init timer with NULL callback function!\n")); + } +#endif + +#if DBG + ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); + { + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prPendingTimer; + + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prPendingTimer); + ASSERT(prPendingTimer != prTimer); + } + } +#endif + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->u4Data = u4Data; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +cnmTimerStopTimer_impl ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN BOOLEAN fgAcquireSpinlock + ) +{ + P_ROOT_TIMER prRootTimer; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + prRootTimer = &prAdapter->rRootTimer; + + if (fgAcquireSpinlock) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } + + if (timerPendingTimer(prTimer)) { + LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead, + &prTimer->rLinkEntry); + + /* Reduce dummy timeout for power saving, especially HIF activity. + * If two or more timers exist and being removed timer is smallest, + * this dummy timeout will still happen, but it is OK. + */ + if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { + kalCancelTimer(prAdapter->prGlueInfo); + + if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + } + } + + if (fgAcquireSpinlock) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerStopTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer + ) +{ + ASSERT(prAdapter); + ASSERT(prTimer); + + cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to start a timer with wake_lock. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] u4TimeoutMs Timeout to issue the timer and call back function +* (unit: ms). +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerStartTimer ( + IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN UINT_32 u4TimeoutMs + ) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + OS_SYSTIME rExpiredSysTime, rTimeoutSystime; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList= &prRootTimer->rLinkHead; + + /* If timeout interval is larger than 1 minute, the mod value is set + * to the timeout value first, then per minutue. + */ + if (u4TimeoutMs > MSEC_PER_MIN) { + ASSERT(u4TimeoutMs <= ((UINT_32)0xFFFF * MSEC_PER_MIN)); + + prTimer->u2Minutes = (UINT_16)(u4TimeoutMs / MSEC_PER_MIN); + u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN); + if (u4TimeoutMs == 0) { + u4TimeoutMs = MSEC_PER_MIN; + prTimer->u2Minutes--; + } + } + else { + prTimer->u2Minutes = 0; + } + + /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */ + ASSERT(u4TimeoutMs < (((UINT_32)0x80000000 - MSEC_PER_SEC) / KAL_HZ)); + rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); + rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; + + /* If no timer pending or the fast time interval is used. */ + if (LINK_IS_EMPTY(prTimerList) || + TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + + prRootTimer->rNextExpiredSysTime = rExpiredSysTime; + cnmTimerSetTimer(prAdapter, rTimeoutSystime); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) { + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to check the timer list. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerDoTimeOutCheck ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + UINT_32 u4TimeoutData; + BOOLEAN fgNeedWakeLock; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* acquire spin lock */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList= &prRootTimer->rLinkHead; + + rCurSysTime = kalGetTimeTick(); + + /* Set the permitted max timeout value for new one */ + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prTimer); + + /* Check if this entry is timeout. */ + if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { + cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); + + pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; + u4TimeoutData = prTimer->u4Data; + + if (prTimer->u2Minutes > 0) { + prTimer->u2Minutes--; + prTimer->rExpiredSysTime = + rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN); + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } + else if (pfMgmtTimeOutFunc) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + (pfMgmtTimeOutFunc)(prAdapter, u4TimeoutData); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } + + /* Search entire list again because of nest del and add timers + * and current MGMT_TIMER could be volatile after stopped + */ + prLinkEntry = (P_LINK_ENTRY_T)prTimerList; + + prRootTimer->rNextExpiredSysTime = + rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } + else if (TIME_BEFORE(prTimer->rExpiredSysTime, + prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; + } + } /* end of for loop */ + + /* Setup the prNext timeout event. It is possible the timer was already + * set in the above timeout callback function. + */ + fgNeedWakeLock = FALSE; + if (!LINK_IS_EMPTY(prTimerList)) { + ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); + + fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) + ((INT_32)prRootTimer->rNextExpiredSysTime - (INT_32)rCurSysTime)); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c new file mode 100755 index 000000000000..278e5d7627a1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c @@ -0,0 +1,831 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/hem_mbox.c#3 $ +*/ + +/*! \file "hem_mbox.c" + \brief + +*/ + + + +/* +** $Log: hem_mbox.c $ +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 05 03 2012 cp.wu + * [WCXRP00001231] [MT6620 Wi-Fi][MT5931][Driver] Correct SCAN_V2 related debugging facilities within hem_mbox.c + * correct for debug message string table by adding missed scan_v2 related definitions. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 17 2012 yuche.tsai + * NULL + * Update mgmt frame filter setting. + * Please also update FW 2.1 + * + * 01 13 2012 yuche.tsai + * NULL + * WiFi Hot Spot Tethering for ICS ALPHA testing version. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 15 2011 cm.chang + * NULL + * Add exception handle for NULL function pointer of mailbox message + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 07 2011 yuche.tsai + * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response.[WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add invitation support. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update bowString and channel grant. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 12 08 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support concurrent networks. + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 16 2010 cm.chang + * NULL + * Remove unused message ID + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 26 2010 yuche.tsai + * NULL + * Add P2P Connection Abort Event Message handler. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 yarco.yang + * NULL + * Fixed Driver ASSERT at mboxInitMsgMap() + * + * 08 24 2010 chinghwa.yu + * NULL + * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. + * Update saa_fsm for BOW. + * + * 08 23 2010 chinghwa.yu + * NULL + * Add CFG_ENABLE_BT_OVER_WIFI. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 16 2010 yuche.tsai + * NULL + * Add debug message for newly add P2P message. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some function entry for P2P FSM under provisioning phase.. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some events to P2P Module. + * + * 08 05 2010 yuche.tsai + * NULL + * Add message box event for P2P device switch on & device discovery. + * + * 08 04 2010 cp.wu + * NULL + * remove unused mailbox message definitions. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * message table should not be commented out by compilation option without modifying header file + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 yuche.tsai + * + * Add wifi direct scan done callback. + * + * 07 09 2010 cp.wu + * + * change handler of MID_MNY_CNM_CONNECTION_ABORT from NULL to mboxDummy. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable currently migrated message call-backs. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix file merge error + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_QOS_ACTION_FRAME + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_BA_ACTION_FRAME + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * MID_RXM_MQM_BA_ACTION_FRAME + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Develop partial DPD code + * + * 02 11 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Updated arMsgMapTable for MID_RXM_MQM_QOS_ACTION_FRAME + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Dec 9 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add hemRunEventScanDone() to arMsgMapTable[] + * + * Dec 4 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix mboxDummy() didn't free prMsgHdr + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add saaAisJoinComplete event handler + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed the handler function name in arMsgMapTable for MID_RXM_MQM_BA_ACTION_FRAME + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added MID_RXM_MQM_BA_ACTION_FRAME to MsgMapTable + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MSG Handler (remove dummy and add for SAA) + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmRunEventAbort() event handler + * + * Nov 11 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Nov 10 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add more MSG_HNDL_ENTRY_T to avoid ASSERT() in mboxInitMsgMap() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add SCN message and function entry to arMsgMapTable[] + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix sorting algorithm in mboxInitMsgMap() + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugMsg[] = { + (PUINT_8)DISP_STRING("MID_MNY_CNM_CH_REQ"), + (PUINT_8)DISP_STRING("MID_MNY_CNM_CH_ABORT"), + (PUINT_8)DISP_STRING("MID_CNM_AIS_CH_GRANT"), + (PUINT_8)DISP_STRING("MID_CNM_P2P_CH_GRANT"), + (PUINT_8)DISP_STRING("MID_CNM_BOW_CH_GRANT"), + + (PUINT_8)DISP_STRING("MID_AIS_SCN_SCAN_REQ"), + (PUINT_8)DISP_STRING("MID_AIS_SCN_SCAN_REQ_V2"), + (PUINT_8)DISP_STRING("MID_AIS_SCN_SCAN_CANCEL"), + (PUINT_8)DISP_STRING("MID_P2P_SCN_SCAN_REQ"), + (PUINT_8)DISP_STRING("MID_P2P_SCN_SCAN_REQ_V2"), + (PUINT_8)DISP_STRING("MID_P2P_SCN_SCAN_CANCEL"), + (PUINT_8)DISP_STRING("MID_BOW_SCN_SCAN_REQ"), + (PUINT_8)DISP_STRING("MID_BOW_SCN_SCAN_REQ_V2"), + (PUINT_8)DISP_STRING("MID_BOW_SCN_SCAN_CANCEL"), + (PUINT_8)DISP_STRING("MID_RLM_SCN_SCAN_REQ"), + (PUINT_8)DISP_STRING("MID_RLM_SCN_SCAN_REQ_V2"), + (PUINT_8)DISP_STRING("MID_RLM_SCN_SCAN_CANCEL"), + (PUINT_8)DISP_STRING("MID_SCN_AIS_SCAN_DONE"), + (PUINT_8)DISP_STRING("MID_SCN_P2P_SCAN_DONE"), + (PUINT_8)DISP_STRING("MID_SCN_BOW_SCAN_DONE"), + (PUINT_8)DISP_STRING("MID_SCN_RLM_SCAN_DONE"), + + (PUINT_8)DISP_STRING("MID_OID_AIS_FSM_JOIN_REQ"), + (PUINT_8)DISP_STRING("MID_OID_AIS_FSM_ABORT"), + (PUINT_8)DISP_STRING("MID_AIS_SAA_FSM_START"), + (PUINT_8)DISP_STRING("MID_AIS_SAA_FSM_ABORT"), + (PUINT_8)DISP_STRING("MID_SAA_AIS_JOIN_COMPLETE"), + +#if CFG_ENABLE_BT_OVER_WIFI + (PUINT_8)DISP_STRING("MID_BOW_SAA_FSM_START"), + (PUINT_8)DISP_STRING("MID_BOW_SAA_FSM_ABORT"), + (PUINT_8)DISP_STRING("MID_SAA_BOW_JOIN_COMPLETE"), +#endif + +#if CFG_ENABLE_WIFI_DIRECT + (PUINT_8)DISP_STRING("MID_P2P_SAA_FSM_START"), + (PUINT_8)DISP_STRING("MID_P2P_SAA_FSM_ABORT"), + (PUINT_8)DISP_STRING("MID_SAA_P2P_JOIN_COMPLETE"), + + (PUINT_8)DISP_STRING("MID_MNY_P2P_FUN_SWITCH"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_DEVICE_DISCOVERY"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_CONNECTION_REQ"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_CONNECTION_ABORT"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_BEACON_UPDATE"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_STOP_AP"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_CHNL_REQ"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_CHNL_ABORT"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_MGMT_TX"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_GROUP_DISSOLVE"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_MGMT_FRAME_REGISTER"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_START_AP"), + (PUINT_8)DISP_STRING("MID_MNY_P2P_UPDATE_IE_BUF"), + #endif + +#if CFG_SUPPORT_ADHOC + //(PUINT_8)DISP_STRING("MID_AIS_CNM_CREATE_IBSS_REQ"), + //(PUINT_8)DISP_STRING("MID_CNM_AIS_CREATE_IBSS_GRANT"), + //(PUINT_8)DISP_STRING("MID_AIS_CNM_MERGE_IBSS_REQ"), + //(PUINT_8)DISP_STRING("MID_CNM_AIS_MERGE_IBSS_GRANT"), + (PUINT_8)DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (PUINT_8)DISP_STRING("MID_SAA_AIS_FSM_ABORT") +}; +/*lint -restore */ +#endif /* DBG */ + +/* This message entry will be re-ordered based on the message ID order + * by invoking mboxInitMsgMap() + */ +static MSG_HNDL_ENTRY_T arMsgMapTable[] = { + { MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege }, + { MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege }, + { MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant }, +#if CFG_ENABLE_WIFI_DIRECT + { MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant }, /*set in gl_p2p_init.c*/ +#else + { MID_CNM_P2P_CH_GRANT, mboxDummy }, +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + { MID_CNM_BOW_CH_GRANT, bowRunEventChGrant }, +#else + { MID_CNM_BOW_CH_GRANT, mboxDummy }, +#endif + + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + { MID_AIS_SCN_SCAN_REQ, scnFsmMsgStart }, + { MID_AIS_SCN_SCAN_REQ_V2, scnFsmMsgStart }, + { MID_AIS_SCN_SCAN_CANCEL, scnFsmMsgAbort }, + { MID_P2P_SCN_SCAN_REQ, scnFsmMsgStart }, + { MID_P2P_SCN_SCAN_REQ_V2, scnFsmMsgStart }, + { MID_P2P_SCN_SCAN_CANCEL, scnFsmMsgAbort }, + { MID_BOW_SCN_SCAN_REQ, scnFsmMsgStart }, + { MID_BOW_SCN_SCAN_REQ_V2, scnFsmMsgStart }, + { MID_BOW_SCN_SCAN_CANCEL, scnFsmMsgAbort }, + { MID_RLM_SCN_SCAN_REQ, scnFsmMsgStart }, + { MID_RLM_SCN_SCAN_REQ_V2, scnFsmMsgStart }, + { MID_RLM_SCN_SCAN_CANCEL, scnFsmMsgAbort }, + { MID_SCN_AIS_SCAN_DONE, aisFsmRunEventScanDone }, +#if CFG_ENABLE_WIFI_DIRECT + { MID_SCN_P2P_SCAN_DONE, p2pFsmRunEventScanDone }, /*set in gl_p2p_init.c*/ +#else + { MID_SCN_P2P_SCAN_DONE, mboxDummy }, +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + { MID_SCN_BOW_SCAN_DONE, bowResponderScanDone }, +#else + { MID_SCN_BOW_SCAN_DONE, mboxDummy }, +#endif + { MID_SCN_RLM_SCAN_DONE, rlmObssScanDone }, + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + { MID_OID_AIS_FSM_JOIN_REQ, aisFsmRunEventAbort }, + { MID_OID_AIS_FSM_ABORT, aisFsmRunEventAbort }, + { MID_AIS_SAA_FSM_START, saaFsmRunEventStart }, + { MID_AIS_SAA_FSM_ABORT, saaFsmRunEventAbort }, + { MID_SAA_AIS_JOIN_COMPLETE, aisFsmRunEventJoinComplete }, + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + { MID_BOW_SAA_FSM_START, saaFsmRunEventStart }, + { MID_BOW_SAA_FSM_ABORT, saaFsmRunEventAbort }, + { MID_SAA_BOW_JOIN_COMPLETE, bowFsmRunEventJoinComplete }, +#endif + +#if CFG_ENABLE_WIFI_DIRECT /*set in gl_p2p_init.c*/ + { MID_P2P_SAA_FSM_START, saaFsmRunEventStart }, + { MID_P2P_SAA_FSM_ABORT, saaFsmRunEventAbort }, + { MID_SAA_P2P_JOIN_COMPLETE, p2pFsmRunEventJoinComplete },// TODO: p2pFsmRunEventJoinComplete + + { MID_MNY_P2P_FUN_SWITCH, p2pFsmRunEventSwitchOPMode }, + { MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest }, + { MID_MNY_P2P_CONNECTION_REQ, p2pFsmRunEventConnectionRequest }, + { MID_MNY_P2P_CONNECTION_ABORT, p2pFsmRunEventConnectionAbort }, + { MID_MNY_P2P_BEACON_UPDATE, p2pFsmRunEventBeaconUpdate }, + { MID_MNY_P2P_STOP_AP, p2pFsmRunEventStopAP }, + { MID_MNY_P2P_CHNL_REQ, p2pFsmRunEventChannelRequest }, + { MID_MNY_P2P_CHNL_ABORT, p2pFsmRunEventChannelAbort }, + { MID_MNY_P2P_MGMT_TX, p2pFsmRunEventMgmtFrameTx }, + { MID_MNY_P2P_GROUP_DISSOLVE, p2pFsmRunEventDissolve }, + { MID_MNY_P2P_MGMT_FRAME_REGISTER, p2pFsmRunEventMgmtFrameRegister }, + { MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister }, + { MID_MNY_P2P_START_AP, p2pFsmRunEventStartAP }, + { MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame }, +#if CFG_SUPPORT_WFD + { MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate }, +#endif + +#endif + +#if CFG_SUPPORT_ADHOC + { MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer }, +#endif /* CFG_SUPPORT_ADHOC */ + + { MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort } +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if DBG +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, ("DO MSG [%d: %s]\n", prMsg->eMsgId, apucDebugMsg[prMsg->eMsgId])); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, ("NULL fptr for MSG [%d]\n", prMsg->eMsgId)); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#else +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, ("DO MSG [%d]\n", prMsg->eMsgId)); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, ("NULL fptr for MSG [%d]\n", prMsg->eMsgId)); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxInitMsgMap ( + VOID + ) +{ + UINT_32 i, idx; + MSG_HNDL_ENTRY_T rTempEntry; + + ASSERT((sizeof(arMsgMapTable) / sizeof(MSG_HNDL_ENTRY_T)) == MID_TOTAL_NUM); + + for (i = 0; i < MID_TOTAL_NUM; i++) { + if (arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i) { + continue; + } + for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { + if (arMsgMapTable[idx].eMsgId == (ENUM_MSG_ID_T) i) { + break; + } + } + ASSERT(idx < MID_TOTAL_NUM); + if (idx >= MID_TOTAL_NUM) { + continue; + } + + /* Swap target entry and current entry */ + rTempEntry.eMsgId = arMsgMapTable[idx].eMsgId; + rTempEntry.pfMsgHndl= arMsgMapTable[idx].pfMsgHndl; + + arMsgMapTable[idx].eMsgId = arMsgMapTable[i].eMsgId; + arMsgMapTable[idx].pfMsgHndl = arMsgMapTable[i].pfMsgHndl; + + arMsgMapTable[i].eMsgId = rTempEntry.eMsgId; + arMsgMapTable[i].pfMsgHndl = rTempEntry.pfMsgHndl; + } + + /* Verify the correctness of final message map */ + for (i = 0; i < MID_TOTAL_NUM; i++) { + ASSERT(arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i); + while (arMsgMapTable[i].eMsgId != (ENUM_MSG_ID_T) i); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxSetup ( + IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId + ) +{ + P_MBOX_T prMbox; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INITIALIZE(&prMbox->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxSendMsg ( + IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, + IN P_MSG_HDR_T prMsg, + IN EUNM_MSG_SEND_METHOD_T eMethod + ) +{ + P_MBOX_T prMbox; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + switch (eMethod) { + case MSG_SEND_METHOD_BUF: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INSERT_TAIL(&prMbox->rLinkHead, &prMsg->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + // to wake up main service thread + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + break; + + case MSG_SEND_METHOD_UNBUF: + MBOX_HNDL_MSG(prAdapter, prMsg); + break; + + default: + ASSERT(0); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxRcvAllMsg ( + IN P_ADAPTER_T prAdapter, + ENUM_MBOX_ID_T eMboxId + ) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead) ) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* Initialize Mailbox */ + mboxInitMsgMap(); + + /* Setup/initialize each mailbox */ + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { + mboxSetup(prAdapter, i); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxDestroy ( + IN P_ADAPTER_T prAdapter + ) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + UINT_8 i; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { + prMbox = &(prAdapter->arMbox[i]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead) ) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + cnmMemFree(prAdapter, prMsg); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is dummy function to prevent empty arMsgMapTable[] for compiling. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxDummy ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); + + return; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c new file mode 100755 index 000000000000..270bdf97a71e --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c @@ -0,0 +1,102 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/mib.c#1 $ +*/ + +/*! \file "mib.c" + \brief This file includes the mib default vale and functions. +*/ + + + +/* +** $Log: mib.c $ + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add mib.c. + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[] = { + {RATE_SET_HR_DSSS, TRUE, FALSE }, /* For PHY_TYPE_HR_DSSS_INDEX(0) */ + {RATE_SET_ERP, TRUE, TRUE }, /* For PHY_TYPE_ERP_INDEX(1) */ + {RATE_SET_ERP_P2P, TRUE, TRUE }, /* For PHY_TYPE_ERP_P2P_INDEX(2) */ + {RATE_SET_OFDM, FALSE, FALSE }, /* For PHY_TYPE_OFDM_INDEX(3) */ +}; + +NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[AD_HOC_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS}, /* For AD_HOC_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP}, /* For AD_HOC_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP}, /* For AD_HOC_MODE_11G(2) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM}, /* For AD_HOC_MODE_11A(3) */ +}; + +NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS}, /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP}, /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP}, /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P}, /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM}, /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c new file mode 100755 index 000000000000..d03d8338a261 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c @@ -0,0 +1,99 @@ +/* +** $Id: @(#) p2p_assoc.c@@ +*/ + +/*! \file "p2p_assoc.c" + \brief This file includes the Wi-Fi Direct association-related functions. + + This file includes the association-related functions. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for P2P Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +PUINT_8 +p2pBuildReAssocReqFrameCommonIEs( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucBuffer + ) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, + prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c new file mode 100755 index 000000000000..d9aa1a130034 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c @@ -0,0 +1,66 @@ +/* +** $Id: @(#) p2p_bss.c@@ +*/ + +/*! \file "p2p_bss.c" + \brief This file contains the functions for creating p2p BSS(AP). + + This file contains the functions for BSS(AP). We may create a BSS + network, or merge with exist IBSS network and sending Beacon Frame or reply + the Probe Response Frame for received Probe Request Frame. +*/ + + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c new file mode 100755 index 000000000000..7e050c50af76 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c @@ -0,0 +1,3436 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/mgmt/p2p_fsm.c#61 $ +*/ + +/*! \file "p2p_fsm.c" + \brief This file defines the FSM for P2P Module. + + This file defines the FSM for P2P Module. +*/ + + + +/* +** $Log: p2p_fsm.c $ +** +** 12 20 2012 yuche.tsai +** [ALPS00410124] [Rose][Free Test][KE][rlmUpdateParamsForAP]The device reboot automaticly and then "Fatal/Kernel" pops up during use data service.(Once) +** Fix possible NULL station record cause KE under AP mode. +** May due to variable uninitial. +** Review: http://mtksap20:8080/go?page=NewReview&reviewid=49970 +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 08 21 2012 yuche.tsai +** NULL +** fix disconnect indication. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** Fix p2p bug find on ALPS.JB trunk. +** +** 07 27 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update for driver unload KE issue. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Fix the compile flag of enhancement. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000808] [Volunteer Patch][MT6620][Driver/FW] Device discoverability issue fix + * Change device discoverability methodology. From driver SCAN to FW lock channel. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000833] [Volunteer Patch][WiFi Direct][Driver] Service Discovery Frame RX Indicate Issue + * Fix Service Discovery Race Condition Issue. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 21 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix an issue of accepting connection of GO. + * + * 06 21 2011 yuche.tsai + * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability + * Drop GAS frame when SD is not enabled. + * + * 06 20 2011 yuche.tsai + * NULL + * Fix compile error. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix connection indication twice issue. + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 20 2011 yuche.tsai + * [WCXRP00000795] [Volunteer Patch][MT6620][Driver] GO can not connect second device issue + * Solve P2P GO can not formation with second device issue. + * + * 06 14 2011 yuche.tsai + * NULL + * Change disconnect feature. + * + * 06 10 2011 yuche.tsai + * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability[WCXRP00000776] [Need Patch][MT6620][Driver] MT6620 response probe request of P2P device with P2P IE under Hot Spot mode. + * 1. Dynamic enable SD capability after P2P supplicant ready. + * 2. Avoid response probe respone with p2p IE when under hot spot mode. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 05 26 2011 yuche.tsai + * [WCXRP00000745] Support accepting connection after one Group Connection Lost. + +After Group Formation & lost connection, if MT6620 behave as: + +1. GO: It would keep under GO state until been dissolved by supplicant. + + At this time, other P2P device can use join method to join this group. + + +2. GC: It would keep on searching target GO or target device until been dissolved by supplicant. + +At this time, it would ignore other P2P device formation request. + + +-- + +Modification: Make driver to accept GO NEGO REQ at this time, to let user decide to accept new connection or not. + + * [Volunteer Patch][MT6620][Driver] + * Driver would indicate connection request, if password ID is not ready but connection request is issued. + * + * 05 18 2011 yuche.tsai + * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. + * A solution for both connection request & IO control. + * + * 05 16 2011 yuche.tsai + * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. + * Fix SD request can not send out issue. + * + * 05 09 2011 terry.wu + * [WCXRP00000711] [MT6620 Wi-Fi][Driver] Set Initial value of StaType in StaRec for Hotspot Client + * Set initial value of StaType in StaRec for hotspot client. + * + * 05 04 2011 yuche.tsai + * [WCXRP00000697] [Volunteer Patch][MT6620][Driver] + * Bug fix for p2p descriptor is NULL if BSS descriptor is found first. + * + * 05 04 2011 yuche.tsai + * NULL + * Support partial persistent group function. + * + * 05 02 2011 yuche.tsai + * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. + * Clear formation flag after formation timeout. + * + * 04 20 2011 yuche.tsai + * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition when add scan & query scan result at the same time. + * Fix side effect while starting ATGO. + * + * 04 20 2011 yuche.tsai + * NULL + * Fix ASSERT issue in FW, side effect of last change. + * + * 04 19 2011 yuche.tsai + * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition when add scan & query scan result at the same time. + * Workaround for multiple device connection, before invitation ready. + * + * 04 19 2011 yuche.tsai + * [WCXRP00000665] [Wifi Direct][MT6620 E4] When use Ralink's dongle to establish wifi direct connection with PBC. But 6573 always not pop accept option to establish connection. + * Support connection indication when GO NEGO REQ doesn't have configure method, instead it has PasswordID. + * + * 04 18 2011 yuche.tsai + * NULL + * Fix error. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Fix a connection issue. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Fix the channel issue of AP mode. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Connection flow refine for Sigma test. + * + * 04 09 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix Device discoverability related issue. + * + * 04 09 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix bug for Device Discoverability. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix compile error. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 03 28 2011 yuche.tsai + * NULL + * Fix a possible issue for retry join when media status connected. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 24 2011 yuche.tsai + * NULL + * Assign AID before change STA_REC state to state 3. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix Response Rate Issue when TX Auth Rsp Frame under P2P Mode. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix issue of connection to one GC. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix ASSERT issue when starting Hot-spot. + * + * 03 22 2011 yuche.tsai + * NULL + * When Target Information is not available, change to passive mode. + * + * 03 22 2011 yuche.tsai + * NULL + * Fix one connection issue while using Keypad to connect a GO. + * + * 03 22 2011 yuche.tsai + * NULL + * 1. Fix two issues that may cause kernel panic. + * + * 03 22 2011 yuche.tsai + * NULL + * Fix GC connect to other device issue. + * + * 03 22 2011 yuche.tsai + * NULL + * 1.Shorten the LISTEN interval. + * 2. Fix IF address issue when we are GO + * 3. Fix LISTEN channel issue. + * + * 03 22 2011 yuche.tsai + * NULL + * Modify formation policy setting. + * + * 03 21 2011 yuche.tsai + * NULL + * Solve Listen State doesn't response probe response issue. + * + * 03 21 2011 yuche.tsai + * NULL + * Change P2P Connection Request Flow. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue + * Indicate the correct Group SSID when join on Group. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue + * Support the third P2P device to join GO/GC group. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000578] [Volunteer Patch][MT6620][Driver] Separate Connection Request from general IOCTL + * Separate connection request from general IOCTL. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 17 2011 yuche.tsai + * NULL + * When AIS is connect to an AP, Hot Spot would be enabled under fixed same channel. + * + * 03 17 2011 yuche.tsai + * NULL + * Solve the Group Info IE in Probe Response incorrect issue. + * + * 03 17 2011 yuche.tsai + * NULL + * Release Channel after Join Complete. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix local configure method issue. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 14 2011 yuche.tsai + * NULL + * . + * + * 03 14 2011 yuche.tsai + * NULL + * Fix password ID issue. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 08 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue[WCXRP00000509] [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. + * . + * + * 03 07 2011 yuche.tsai + * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 04 2011 wh.su + * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue + * fixed the p2p action frame type check for device request indication. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Service Discovery RX packet buffer pointer. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 21 2011 yuche.tsai + * [WCXRP00000481] [Volunteer Patch][MT6620][FW] Scan hang under concurrent case. + * Fix all BE issue of WSC or P2P IE. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the wsc config method mapping to driver used config method issue. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000479] [Volunteer Patch][MT6620][Driver] Probe Response of P2P using 11b rate. + * Update basic rate to FW, after P2P is initialed. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame during search phase do not contain P2P wildcard SSID. + * Use P2P Wildcard SSID when scan type of P2P_WILDCARD_SSID is set. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC IE BE format issue. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 16 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * fixed the probe request send out without WSC IE issue (at P2P). + * + * 02 16 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * If two station connected to the Hot-Spot and one disconnect, FW would get into an infinite loop + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix re-connection issue after RX deauthentication. + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix conneciton issue after disconnect with AP. + * + * 02 12 2011 yuche.tsai + * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. + * P2P Create Station Type according to Target BSS capability. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Support Disassoc & Deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA module. + * Disconnect every station client when disolve on P2P group. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * 1. Fix Service Disocvery Logical issue. + * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA module. + * Workaround of disable P2P network. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue + * 1. Fixed SSID wrong length issue. + * 2. Under Hot Spot configuration, there won't be any P2P IE. + * 3. Under Hot Spot configuration, P2P FSM won't get into LISTEN state first. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Modify Start GO flow. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix desire phy type set issue. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Add desire phy type set phase I. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix P2P Disconnect Issue. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix compile error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type Definition. + * + * 01 19 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Add P2P QoS Support. + * + * 01 19 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Null NOA attribute setting when no related parameters. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify AAA flow according to CM's comment. + * + * 01 13 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Resolve Channel ZERO issue. (Uninitialized default channel) + * + * 01 13 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Update P2P State Debug Message. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Fix bug when allocating message buffer. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update when STA record is created under AP Mode. + * Update Phy Type Set. When legacy client is connected, it can use 11b rate, + * but if the P2P device is connected, 11b rate is not allowed. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. + * 2. Call cnmP2pIsPermit() before active P2P network. + * 3. Add channel selection support for AP mode. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix Bug of reference to NULL pointer. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify some behavior of AP mode. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix bug of wrong pointer check. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix Compile Error. + * + * 01 11 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Add station record into client list before change it state from STATE_2 to STATE_3. + * + * 01 05 2011 yuche.tsai + * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, but the SSID length is still invalid. + * Specify SSID Type when issue a scan request. + * + * 01 05 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * correct typo + * + * 01 05 2011 george.huang + * [WCXRP00000343] [MT6620 Wi-Fi] Add TSF reset path for concurrent operation + * modify NOA update path for preventing assertion false alarm. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 01 03 2011 wh.su + * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * let the p2p ap mode acept a legacy device join. + * + * 12 22 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Compile Error. + * + * 12 15 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Refine Connection Flow. + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add + * + * 12 08 2010 yuche.tsai + * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. + * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client by checking the P2P IE in assoc req frame. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * The order of invoking nicUpdateBss() and rlm functions + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation & Provision Discovery. + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 30 2010 yuche.tsai + * NULL + * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ + * + * 11 30 2010 yuche.tsai + * NULL + * Update RCIP value when RX assoc request frame. + * + * 11 29 2010 yuche.tsai + * NULL + * Update P2P related function for INVITATION & PROVISION DISCOVERY. + * + * 11 26 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Update P2P PS for NOA function. + * + * 11 25 2010 yuche.tsai + * NULL + * Update Code for Invitation Related Function. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 05 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * fixed the p2p role code error. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * fixed the ASSERT check error + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 19 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine[WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * fixed the compiling error. + * + * 10 14 2010 wh.su + * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * adding a code to support Direct GO with a compiling flag . + * + * 10 08 2010 cp.wu + * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. + * correct erroneous logic: specifying eBand with incompatible eSco + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * fixed the compiling error. + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at WinXP. + * + * 09 07 2010 yuche.tsai + * NULL + * Reset Common IE Buffer of P2P INFO when scan request is issued. + * If an action frame other than public action frame is received, return direcly. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 26 2010 yuche.tsai + * NULL + * Add P2P Connection Abort Event Message handler. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 yuche.tsai + * NULL + * 1. Fix Interface Address from GO Nego Req/Rsp is not correct. + * 2. Fix GO mode does not change media state after station connected. + * 3. Fix STA don't response probe request when there is a connection request. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 20 2010 yuche.tsai + * NULL + * Add Glue Layer indication. + * + * 08 17 2010 yuche.tsai + * NULL + * Fix compile warning under Linux. + * + * 08 17 2010 yuche.tsai + * NULL + * Fix some P2P FSM bug. + * + * 08 16 2010 yuche.tsai + * NULL + * Add random Interface Address Generation support. + * + * 08 16 2010 yuche.tsai + * NULL + * Fix some P2P FSM bug. + * + * 08 16 2010 yuche.tsai + * NULL + * Update P2P FSM code for GO Nego. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Join complete indication. + * + * 08 11 2010 yuche.tsai + * NULL + * Add two boolean in connection request. + * Based on these two boolean value, P2P FSM should + * decide to do invitation or group formation or start a GO directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Update P2P FSM, currently P2P Device Discovery is verified. + * + * 08 05 2010 yuche.tsai + * NULL + * Update P2P FSM for group formation. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 03 2010 cp.wu + * NULL + * limit build always needs spin-lock declaration. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Add P2P FSM code check in. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Update P2P FSM. + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error while enable WIFI_DIRECT support. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Update P2P Function call. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename CFG flag for P2P + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add code to test P2P GO + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add Wi-Fi Direct SSID and P2P GO Test Mode + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify code due to BAND_24G define was changed + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugP2pState[P2P_STATE_NUM] = { + (PUINT_8)DISP_STRING("P2P_STATE_IDLE"), + (PUINT_8)DISP_STRING("P2P_STATE_SCAN"), + (PUINT_8)DISP_STRING("P2P_STATE_AP_CHANNEL_DETECT"), + (PUINT_8)DISP_STRING("P2P_STATE_REQING_CHANNEL"), + (PUINT_8)DISP_STRING("P2P_STATE_CHNL_ON_HAND"), + (PUINT_8)DISP_STRING("P2P_STATE_GC_JOIN") +}; +/*lint -restore */ +#endif /* DBG */ + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* p2pStateXXX : Processing P2P FSM related action. + * p2pFSMXXX : Control P2P FSM flow. + * p2pFuncXXX : Function for doing one thing. + */ +VOID +p2pFsmInit ( + IN P_ADAPTER_T prAdapter + ) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ASSERT_BREAK(prP2pFsmInfo != NULL); + + LINK_INITIALIZE(&(prP2pFsmInfo->rMsgEventQueue)); + LINK_INITIALIZE(&(prP2pBssInfo->rStaRecOfClientList)); + + + prP2pFsmInfo->eCurrentState = prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + prP2pFsmInfo->prTargetBss = NULL; + + cnmTimerInitTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC)p2pFsmRunEventFsmTimeout, + (UINT_32)prP2pFsmInfo); + + //4 <2> Initiate BSS_INFO_T - common part + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_P2P_INDEX); + + + //4 <2.1> Initiate BSS_INFO_T - Setup HW ID + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->ucHwDefaultFixedRateCode = RATE_OFDM_6M; + + + prP2pBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prP2pBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, + &prP2pBssInfo->ucAllSupportedRatesLen); + + prP2pBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } + else { + /* Out of memory. */ + ASSERT(FALSE); + } + + prP2pBssInfo->eCurrentOPMode = OP_MODE_NUM; + + prP2pBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; + prP2pBssInfo->ucPrimaryChannel = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pBssInfo->eBand = BAND_2G4; + prP2pBssInfo->eBssSCO = CHNL_EXT_SCN; + + if (prAdapter->rWifiVar.fgSupportQoS) { + prP2pBssInfo->fgIsQBSS = TRUE; + } + else { + prP2pBssInfo->fgIsQBSS = FALSE; + } + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } while (FALSE); + + return; +} /* p2pFsmInit */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to uninitialize the value in P2P_FSM_INFO_T for +* P2P FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmUninit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pFsmUninit()"); + DBGLOG(P2P, INFO, ("->p2pFsmUninit()\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, OP_MODE_P2P_DEVICE, TRUE); + + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, P2P_STATE_NUM); + + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + wlanAcquirePowerControl(prAdapter); + + /* Release all pending CMD queue. */ + DBGLOG(P2P, TRACE, ("p2pFsmUninit: wlanProcessCommandQueue, num of element:%d\n", prAdapter->prGlueInfo->rCmdQueue.u4NumElem)); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + + wlanReleasePowerControl(prAdapter); + + /* Release pending mgmt frame, + * mgmt frame may be pending by CMD without resource. + */ + kalClearMgmtFramesByNetType(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue*/ + wlanReleasePendingCMDbyNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; + +} /* end of p2pFsmUninit() */ + +VOID +p2pFsmStateTransition ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + BOOLEAN fgIsTransOut = (BOOLEAN)FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (!IS_BSS_ACTIVE(prP2pBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) { + return; + } + + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + fgIsTransOut = fgIsTransOut?FALSE:TRUE; + + if (!fgIsTransOut) { + DBGLOG(P2P, STATE, ("TRANSITION: [%s] -> [%s]\n", + apucDebugP2pState[prP2pFsmInfo->eCurrentState], + apucDebugP2pState[eNextState])); + + /* Transition into current state. */ + prP2pFsmInfo->ePreviousState = prP2pFsmInfo->eCurrentState; + prP2pFsmInfo->eCurrentState = eNextState; + } + + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + if (fgIsTransOut) { + + p2pStateAbort_IDLE(prAdapter, + prP2pFsmInfo, + eNextState); + } + else { + fgIsTransOut = p2pStateInit_IDLE(prAdapter, + prP2pFsmInfo, + prP2pBssInfo, + &eNextState); + } + + break; + case P2P_STATE_SCAN: + if (fgIsTransOut) { + + // Scan done / scan canceled. + p2pStateAbort_SCAN(prAdapter, prP2pFsmInfo, eNextState); + } + else { + // Initial scan request. + p2pStateInit_SCAN(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_AP_CHANNEL_DETECT: + if (fgIsTransOut) { + // Scan done + // Get sparse channel result. + p2pStateAbort_AP_CHANNEL_DETECT(prAdapter, + prP2pFsmInfo, + prP2pSpecificBssInfo, + eNextState); + } + + else { + // Initial passive scan request. + p2pStateInit_AP_CHANNEL_DETECT(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_REQING_CHANNEL: + if (fgIsTransOut) { + + // Channel on hand / Channel canceled. + p2pStateAbort_REQING_CHANNEL(prAdapter, prP2pFsmInfo, eNextState); + } + else { + // Initial channel request. + p2pFuncAcquireCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + break; + case P2P_STATE_CHNL_ON_HAND: + if (fgIsTransOut) { + p2pStateAbort_CHNL_ON_HAND(prAdapter, prP2pFsmInfo, prP2pBssInfo, eNextState); + } + else { + // Initial channel ready. + // Send channel ready event. + // Start a FSM timer. + p2pStateInit_CHNL_ON_HAND(prAdapter, prP2pBssInfo, prP2pFsmInfo); + } + + break; + case P2P_STATE_GC_JOIN: + if (fgIsTransOut) { + + // Join complete / join canceled. + p2pStateAbort_GC_JOIN(prAdapter, + prP2pFsmInfo, + &(prP2pFsmInfo->rJoinInfo), + eNextState); + } + else { + ASSERT(prP2pFsmInfo->prTargetBss != NULL); + + // Send request to SAA module. + p2pStateInit_GC_JOIN(prAdapter, + prP2pFsmInfo, + prP2pBssInfo, + &(prP2pFsmInfo->rJoinInfo), + prP2pFsmInfo->prTargetBss); + } + + break; + default: + break; + } + + } while (fgIsTransOut); + +} /* p2pFsmStateTransition */ + + +VOID +p2pFsmRunEventSwitchOPMode ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchOpMode = (P_MSG_P2P_SWITCH_OP_MODE_T)prMsgHdr; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwitchOpMode != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventSwitchOPMode\n")); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prSwitchOpMode->eOpMode >= OP_MODE_NUM) { + ASSERT(FALSE); + break; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, + prP2pBssInfo, + prSwitchOpMode->eOpMode, + TRUE); + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + +} /* p2pFsmRunEventSwitchOPMode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle scan done event during Device Discovery. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventScanDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T)NULL; + P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE)NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + + /* This scan done event is either for "SCAN" phase or "SEARCH" state or "LISTEN" state. + * The scan done for SCAN phase & SEARCH state doesn't imply Device + * Discovery over. + */ + DBGLOG(P2P, TRACE, ("P2P Scan Done Event\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE)prMsgHdr; + + if (prScanDoneMsg->ucSeqNum != prScanReqInfo->ucSeqNumOfScnMsg) { + /* Scan Done message sequence number mismatch. + * Ignore this event. (P2P FSM issue two scan events.) + */ + /* The scan request has been cancelled. + * Ignore this message. It is possible. + */ + DBGLOG(P2P, TRACE, ("P2P Scan Don SeqNum:%d <-> P2P Fsm SCAN Msg:%d\n", + prScanDoneMsg->ucSeqNum, + prScanReqInfo->ucSeqNumOfScnMsg)); + + break; + } + + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_SCAN: + { + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->fgIsConnRequest) { + + if ((prP2pFsmInfo->prTargetBss = p2pFuncKeepOnConnection(prAdapter, + &prP2pFsmInfo->rConnReqInfo, + &prP2pFsmInfo->rChnlReqInfo, + &prP2pFsmInfo->rScanReqInfo)) == NULL) { + eNextState = P2P_STATE_SCAN; + } + else { + eNextState = P2P_STATE_REQING_CHANNEL; + } + + } + else { + eNextState = P2P_STATE_IDLE; + } + + } + break; + case P2P_STATE_AP_CHANNEL_DETECT: + eNextState = P2P_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event without being chanceled. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pFsmStateTransition(prAdapter, + prP2pFsmInfo, + eNextState); + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventScanDone */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when channel is granted by CNM module from FW. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventChGrant ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T)NULL; + UINT_8 ucTokenID = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("P2P Run Event Channel Grant\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prMsgChGrant = (P_MSG_CH_GRANT_T)prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prP2pFsmInfo->u4GrantInterval = prMsgChGrant->u4GrantInterval; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChannelReqType) { + case CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL: + eNextState = P2P_STATE_CHNL_ON_HAND; + break; + case CHANNEL_REQ_TYPE_GC_JOIN_REQ: + eNextState = P2P_STATE_GC_JOIN; + break; + case CHANNEL_REQ_TYPE_GO_START_BSS: + eNextState = P2P_STATE_IDLE; + break; + default: + break; + } + + p2pFsmStateTransition(prAdapter, + prP2pFsmInfo, + eNextState); + break; + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea before leaving the states. + */ + ASSERT(FALSE); + break; + } + + } + else { + /* Channel requsted, but released. */ + ASSERT(!prChnlReqInfo->fgIsChannelRequested); + } + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; + +} /* p2pFsmRunEventChGrant */ + + +VOID +p2pFsmRunEventChannelRequest ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + P_MSG_P2P_CHNL_REQUEST_T prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T)prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventChannelRequest\n")); + + /* Special case of time renewing for same frequency. */ + if ((prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) && + (prChnlReqInfo->ucReqChnlNum == prP2pChnlReqMsg->rChannelInfo.ucChannelNum) && + (prChnlReqInfo->eBand == prP2pChnlReqMsg->rChannelInfo.eBand) && + (prChnlReqInfo->eChnlSco == prP2pChnlReqMsg->eChnlSco)) { + + ASSERT(prChnlReqInfo->fgIsChannelRequested == TRUE); + ASSERT(prChnlReqInfo->eChannelReqType == CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL); + + prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; + prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; + + /* Re-enter the state. */ + eNextState = P2P_STATE_CHNL_ON_HAND; + } + else { + + // Make sure the state is in IDLE state. + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; /* Cookie can only be assign after abort.(for indication) */ + prChnlReqInfo->ucReqChnlNum = prP2pChnlReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pChnlReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pChnlReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL; + + eNextState = P2P_STATE_REQING_CHANNEL; + } + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } while (FALSE); + + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventChannelRequest */ + + +VOID +p2pFsmRunEventChannelAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_MSG_P2P_CHNL_ABORT_T prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T)NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T)prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventChannelAbort\n")); + + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) && + (prChnlReqInfo->fgIsChannelRequested)) { + + ASSERT((prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL || + (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND))); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventChannelAbort */ + + + +VOID +p2pFsmRunEventScanRequest ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T)NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T)NULL; + UINT_32 u4ChnlListSize = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T)prMsgHdr; + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventScanRequest\n")); + + // Make sure the state is in IDLE state. + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + + // Channel List + prScanReqInfo->ucNumChannelList = prP2pScanReqMsg->u4NumChannel; + DBGLOG(P2P, TRACE, ("Scan Request Channel List Number: %d\n", prScanReqInfo->ucNumChannelList)); + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) { + DBGLOG(P2P, TRACE, ("Channel List Number Overloaded: %d, change to: %d\n", + prScanReqInfo->ucNumChannelList, + MAXIMUM_OPERATION_CHANNEL_LIST)); + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + u4ChnlListSize = sizeof(RF_CHANNEL_INFO_T) * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); + + // TODO: I only take the first SSID. Multiple SSID may be needed in the future. + // SSID + if (prP2pScanReqMsg->i4SsidNum >= 1) { + + kalMemCopy(&(prScanReqInfo->rSsidStruct), + prP2pScanReqMsg->prSSID, + sizeof(P2P_SSID_STRUCT_T)); + } + else { + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + } + + // IE Buffer + kalMemCopy(prScanReqInfo->aucIEBuf, + prP2pScanReqMsg->pucIEBuf, + prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + + + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + +} /* p2pFsmRunEventScanRequest */ + + +VOID +p2pFsmRunEventScanAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventScanAbort\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventScanAbort */ + + + + + +VOID +p2pFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventAbort\n")); + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + } + else if (prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL) { + /* 2012/08/06: frog + * Prevent Start GO. + */ + prP2pBssInfo->eIntendOPMode = OP_MODE_NUM; + } + + // For other state, is there any special action that should be take before leaving? + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + else { + /* P2P State IDLE. */ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (prChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } + + cnmTimerStopTimer(prAdapter, &(prP2pFsmInfo->rP2pFsmTimeoutTimer)); + } + + + } while (FALSE); + + return; +} /* p2pFsmRunEventAbort */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle FSM Timeout. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventFsmTimeout ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)u4Param; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + DBGLOG(P2P, TRACE, ("P2P FSM Timeout Event\n")); + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + { + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + if (prChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } + else if (IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } + break; + +// case P2P_STATE_SCAN: +// break; +// case P2P_STATE_AP_CHANNEL_DETECT: +// break; +// case P2P_STATE_REQING_CHANNEL: +// break; + case P2P_STATE_CHNL_ON_HAND: + { + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + break; +// case P2P_STATE_GC_JOIN: +// break; + default: + break; + } + + } while (FALSE); + + return; +} /* p2pFsmRunEventFsmTimeout */ + +VOID +p2pFsmRunEventMgmtFrameTx ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_MSG_P2P_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventMgmtFrameTx\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T)prMsgHdr; + + p2pFuncTxMgmtFrame(prAdapter, + &prP2pFsmInfo->rMgmtTxInfo, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->u8Cookie); + + + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; + +} /* p2pFsmRunEventMgmtTx */ + + +VOID +p2pFsmRunEventStartAP ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventStartAP\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)prMsgHdr; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, ("Beacon interval updated to :%ld \n", prP2pStartAPMsg->u4BcnInterval)); + prP2pBssInfo->u2BeaconInterval = (UINT_16)prP2pStartAPMsg->u4BcnInterval; + } + else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, ("DTIM interval updated to :%ld \n", prP2pStartAPMsg->u4DtimPeriod)); + prP2pBssInfo->ucDTIMPeriod = (UINT_8)prP2pStartAPMsg->u4DtimPeriod; + } + else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pBssInfo->aucSSID, prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen); + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen); + prP2pBssInfo->ucSSIDLen = prP2pSpecificBssInfo->u2GroupSsidLen = prP2pStartAPMsg->u2SsidLen; + } + + + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + + // TODO: JB + /* Privacy & inactive timeout. */ + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + ENUM_P2P_STATE_T eNextState = P2P_STATE_SCAN; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + + if(prP2pFsmInfo->eCurrentState != P2P_STATE_SCAN && + prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + // Make sure the state is in IDLE state. + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + } + + // 20120118: Moved to p2pFuncSwitchOPMode(). + //SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + // sync with firmware + //DBGLOG(P2P, INFO, ("Activate P2P Network. \n")); + //nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + + /* Key to trigger P2P FSM to allocate channel for AP mode. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + + /* Sparse Channel to decide which channel to use. */ + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) && (prP2pConnSettings->ucOperatingChnl == 0)) { + // Sparse Channel Detection using passive mode. + eNextState = P2P_STATE_AP_CHANNEL_DETECT; + } + else { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + +#if 1 + /* 2012-01-27: frog - Channel set from upper layer is the first priority. */ + /* Becuase the channel & beacon is decided by p2p_supplicant. */ + if (prP2pConnSettings->ucOperatingChnl != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + } + + else { + ASSERT(ucPreferedChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + } +#else + if (ucPreferedChnl) { + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + } + else { + ASSERT(prP2pConnSettings->ucOperatingChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + } + +#endif + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + } + + /* If channel is specified, use active scan to shorten the scan time. */ + p2pFsmStateTransition(prAdapter, + prAdapter->rWifiVar.prP2pFsmInfo, + eNextState); + } + + + + } while (FALSE); + + + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventStartAP */ + +VOID +p2pFsmRunEventNetDeviceRegister ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_P2P_NETDEV_REGISTER_T prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; + + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventNetDeviceRegister\n")); + + prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T)prMsgHdr; + + if (prNetDevRegisterMsg->fgIsEnable) { + p2pSetMode((prNetDevRegisterMsg->ucMode == 1)?TRUE:FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) { + ASSERT(prAdapter->fgIsP2PRegistered); + } + + } + else { + if (prAdapter->fgIsP2PRegistered) { + p2pRemove(prAdapter->prGlueInfo); + } + + } + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventNetDeviceRegister */ + + +VOID +p2pFsmRunEventUpdateMgmtFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_P2P_MGMT_FRAME_UPDATE_T prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventUpdateMgmtFrame\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T)prMsgHdr; + + switch (prP2pMgmtFrameUpdateMsg->eBufferType) { + case ENUM_FRAME_TYPE_EXTRA_IE_BEACON: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP: + break; + case ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE: + break; + case ENUM_FRAME_TYPE_BEACON_TEMPLATE: + break; + default: + break; + } + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventUpdateMgmtFrame */ + + +VOID +p2pFsmRunEventBeaconUpdate ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_MSG_P2P_BEACON_UPDATE_T prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventBeaconUpdate\n")); + + printk("p2pFsmRunEventBeaconUpdate\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)prMsgHdr; + + + p2pFuncBeaconUpdate(prAdapter, + prP2pBssInfo, + &prP2pFsmInfo->rBcnContentInfo, + prBcnUpdateMsg->pucBcnHdr, + prBcnUpdateMsg->u4BcnHdrLen, + prBcnUpdateMsg->pucBcnBody, + prBcnUpdateMsg->u4BcnBodyLen); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + //nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + //nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + + + } while (FALSE); + + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + +} /* p2pFsmRunEventBeaconUpdate */ + + +VOID +p2pFsmRunEventStopAP ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventStopAP\n")); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + + DBGLOG(P2P, TRACE, ("Stop Beaconing\n")); + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + } + + + + // 20120118: Moved to p2pFuncSwitchOPMode(). + //UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Enter IDLE state. */ + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + DBGLOG(P2P, INFO, ("Re activate P2P Network. \n")); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + +#if CFG_SUPPORT_WFD + p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); +#endif + + p2pFsmRunEventAbort(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo); +// p2pFsmStateTransition(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo, P2P_STATE_IDLE); + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + +} /* p2pFsmRunEventStopAP */ + +VOID +p2pFsmRunEventConnectionRequest ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T)NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T)prMsgHdr; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventConnectionRequest\n")); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + break; + } + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + + // Make sure the state is in IDLE state. + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + // Update connection request information. + prConnReqInfo->fgIsConnRequest = TRUE; + COPY_MAC_ADDR(prConnReqInfo->aucBssid, prConnReqMsg->aucBssid); + kalMemCopy(&(prConnReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + kalMemCopy(prConnReqInfo->aucIEBuf, prConnReqMsg->aucIEBuf, prConnReqMsg->u4IELen); + prConnReqInfo->u4BufLength = prConnReqMsg->u4IELen; + + /* Find BSS Descriptor first. */ + prP2pFsmInfo->prTargetBss = scanP2pSearchDesc(prAdapter, + prP2pBssInfo, + prConnReqInfo); + + if (prP2pFsmInfo->prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = prConnReqMsg->rChannelInfo.ucChannelNum; + kalMemCopy(&(prScanReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } + else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_REQING_CHANNEL); + } + + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; + +} /* p2pFsmRunEventConnectionRequest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle Connection Request from Supplicant. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventConnectionAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)NULL; + //P_STA_RECORD_T prTargetStaRec = (P_STA_RECORD_T)NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventConnectionAbort: Connection Abort.\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)prMsgHdr; + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + { + UINT_8 aucBCBSSID[] = BC_BSSID; + + if (!prP2pBssInfo->prStaRecOfAP) { + DBGLOG(P2P, TRACE, ("GO's StaRec is NULL\n")); + break; + } + if (UNEQUAL_MAC_ADDR(prP2pBssInfo->prStaRecOfAP->aucMacAddr, prDisconnMsg->aucTargetID) && + UNEQUAL_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCBSSID)) { + DBGLOG(P2P, TRACE, ("Unequal MAC ADDR ["MACSTR":"MACSTR"]\n", + MAC2STR(prP2pBssInfo->prStaRecOfAP->aucMacAddr), + MAC2STR(prDisconnMsg->aucTargetID))); + break; + } + + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, NULL, NULL, 0, 0); + + /* Stop rejoin timer if it is started. */ + // TODO: If it has. + + p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, prDisconnMsg->fgSendDeauth, prDisconnMsg->u2ReasonCode); + + //prTargetStaRec = prP2pBssInfo->prStaRecOfAP; + + /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). hit prStaRecOfAP == NULL. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + prP2pBssInfo->prStaRecOfAP = NULL; + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + break; + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T)NULL; + + DBGLOG(P2P, TRACE, ("Disconnecting with Target ID: "MACSTR"\n", MAC2STR(prDisconnMsg->aucTargetID))); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prDisconnMsg->aucTargetID)) { + + DBGLOG(P2P, TRACE, ("Disconnecting: "MACSTR"\n", MAC2STR(prCurrStaRec->aucMacAddr))); + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCurrStaRec->rLinkEntry); + + /* Glue layer indication. */ + //kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, prCurrStaRec, prDisconnMsg->fgSendDeauth, prDisconnMsg->u2ReasonCode); + + //prTargetStaRec = prCurrStaRec; + + break; + } + } + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + } while (FALSE); + + //20120830 moved into p2pFuncDisconnect() + //if ((!prDisconnMsg->fgSendDeauth) && (prTargetStaRec)) { + // cnmStaRecFree(prAdapter, prTargetStaRec, TRUE); + //} + + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} /* p2pFsmRunEventConnectionAbort */ + + +VOID +p2pFsmRunEventDissolve ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + + // TODO: + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventDissolve\n")); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; +} +WLAN_STATUS +p2pFsmRunEventDeauthTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + do { + + ASSERT_BREAK((prAdapter != NULL) && + (prMsduInfo != NULL)); + + DBGLOG(P2P, TRACE, ("Deauth TX Done\n")); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, ("Station Record NULL, Index:%d\n", prMsduInfo->ucStaRecIndex)); + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + /**/ + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { + DBGLOG(P2P, TRACE, ("No More Client, Media Status DISCONNECTED\n")); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + } + + /* Because the eConnectionState is changed before Deauth TxDone. Dont Check eConnectionState */ + //if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + //} + + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* p2pFsmRunEventDeauthTxDone */ + + +WLAN_STATUS +p2pFsmRunEventMgmtFrameTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_P2P_MGMT_TX_REQ_INFO_T)NULL; + BOOLEAN fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prMgmtTxReqInfo = &(prP2pFsmInfo->rMgmtTxInfo); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(P2P, TRACE, ("Mgmt Frame TX Fail, Status:%d.\n", rTxDoneStatus)); + } + else { + fgIsSuccess = TRUE; + DBGLOG(P2P, TRACE, ("Mgmt Frame TX Done.\n")); + } + + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, + prMsduInfo->prPacket, + (UINT_32)prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFsmRunEventMgmtFrameTxDone */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when JOIN complete message event is received from SAA. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventJoinComplete ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T)NULL; + P_MSG_JOIN_COMP_T prJoinCompMsg = (P_MSG_JOIN_COMP_T)NULL; + P_SW_RFB_T prAssocRspSwRfb = (P_SW_RFB_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, ("P2P Join Complete\n")); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T)prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + prStaRec = prJoinCompMsg->prStaRec; + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prJoinInfo->ucSeqNumOfReqMsg) { + ASSERT(prStaRec == prJoinInfo->prTargetStaRec); + prJoinInfo->fgIsJoinComplete = TRUE; + + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + + //4 <1.1> Change FW's Media State immediately. + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + //4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. + if ((prP2pBssInfo->prStaRecOfAP) && + (prP2pBssInfo->prStaRecOfAP != prStaRec)) { + cnmStaRecChangeState(prAdapter, prP2pBssInfo->prStaRecOfAP, STA_STATE_1); + + cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); + + prP2pBssInfo->prStaRecOfAP = NULL; + } + + //4 <1.3> Update BSS_INFO_T + p2pFuncUpdateBssInfoForJOIN(prAdapter, prP2pFsmInfo->prTargetBss, prStaRec, prAssocRspSwRfb); + + //4 <1.4> Activate current AP's STA_RECORD_T in Driver. + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + +#if CFG_SUPPORT_P2P_RSSI_QUERY + //<1.5> Update RSSI if necessary + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, (INT_8)(RCPI_TO_dBm(prStaRec->ucRCPI)), 0); +#endif + + //4 <1.6> Indicate Connected Event to Host immediately. + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + //p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, prStaRec->aucMacAddr); + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); + + } + else { + /* Join Fail*/ + //4 <2.1> Redo JOIN process with other Auth Type if possible + if (p2pFuncRetryJOIN(prAdapter, prStaRec, prJoinInfo) == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + prBssDesc = prP2pFsmInfo->prTargetBss; + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + prBssDesc->fgIsConnecting = FALSE; + + if( prStaRec->ucJoinFailureCount >=3) { + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); + } + else { + /* Sometime the GO is not ready to response auth. Connect it again*/ + prP2pFsmInfo->prTargetBss = NULL; + } + + + } + + } + } + } + + if (prAssocRspSwRfb) { + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + } + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_GC_JOIN) { + + if(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* Return to IDLE state. */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + else { + //p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + /* one more scan */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } + } + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; + +} /* p2pFsmRunEventJoinComplete */ + + + +VOID +p2pFsmRunEventMgmtFrameRegister ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) { + break; + } + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T)prMsgHdr; + + p2pFuncMgmtFrameRegister(prAdapter, + prMgmtFrameRegister->u2FrameType, + prMgmtFrameRegister->fgIsRegister, + &prP2pFsmInfo->u4P2pPacketFilter); + + + } while (FALSE); + + if (prMsgHdr) { + cnmMemFree(prAdapter, prMsgHdr); + } + + return; + +} /* p2pFsmRunEventMgmtFrameRegister */ + + + + +#if 0 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#endif + + + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventRxDeauthentication ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + UINT_16 u2ReasonCode = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + } + + if (!prStaRec) { + break; + } + + + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + if (prStaRec->ucStaState == STA_STATE_1) { + break; + } + + DBGLOG(P2P, TRACE, ("RX Deauth\n")); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T)prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) { + break; + } + + + prStaRec->u2ReasonCode = u2ReasonCode; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDeauthFrame->aucInfoElem, + u2IELength, + u2ReasonCode); + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T)NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T)NULL; + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + //kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); + + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + /* Findout why someone sent deauthentication frame to us. */ + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, ("Deauth Reason:%d\n", u2ReasonCode)); + + } while (FALSE); + + return; +} /* p2pFsmRunEventRxDeauthentication */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventRxDisassociation ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + UINT_16 u2ReasonCode = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + } + + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prStaRec->ucStaState == STA_STATE_1) { + + break; + } + + DBGLOG(P2P, TRACE, ("RX Disassoc\n")); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T)prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) { + break; + } + + + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDisassocFrame->aucInfoElem, + u2IELength, + prStaRec->u2ReasonCode); + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, prStaRec->u2ReasonCode); + + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T)NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T)NULL; + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + //kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); + + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + + } while (FALSE); + + return; +} /* p2pFsmRunEventRxDisassociation */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when a probe request frame is received. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is accepted & need cancel scan request. +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFsmRunEventRxProbeResponseFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (prBssDesc != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + /* There is a connection request. */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + } while (FALSE); + + return; +} /* p2pFsmRunEventRxProbeResponseFrame */ + + + + + + +VOID +p2pFsmRunEventBeaconTimeout ( + IN P_ADAPTER_T prAdapter + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, ("p2pFsmRunEventBeaconTimeout: Beacon Timeout\n")); + + /* Only client mode would have beacon lost event. */ + ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + NULL, + 0, + REASON_CODE_DISASSOC_INACTIVITY); + + if (prP2pBssInfo->prStaRecOfAP != NULL) { + P_STA_RECORD_T prStaRec = prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_DISASSOC_LEAVING_BSS); + + //20120830 moved into p2pFuncDisconnect() + //cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); + + + } + } + } while (FALSE); + + return; +} /* p2pFsmRunEventBeaconTimeout */ + + + + +#if CFG_SUPPORT_WFD +VOID +p2pFsmRunEventWfdSettingUpdate ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; + WLAN_STATUS rStatus; + + + DBGLOG(P2P, INFO,("p2pFsmRunEventWfdSettingUpdate\n")); + + do { + ASSERT_BREAK((prAdapter != NULL)); + + if (prMsgHdr != NULL) { + prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)prMsgHdr; + prWfdCfgSettings = prMsgWfdCfgSettings->prWfdCfgSettings; + } + else { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO,("WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + prWfdCfgSettings->u4WfdState, + prWfdCfgSettings->u4WfdFlag, + prWfdCfgSettings->u4WfdAdvancedFlag)); + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_SET_WFD_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, + NULL, /* pfCmdTimeoutHandler */ + sizeof(WFD_CFG_SETTINGS_T), /* u4SetQueryInfoLen */ + (PUINT_8)prWfdCfgSettings, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + } while (FALSE); + + return; + +} +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif + + + + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pGenerateP2P_IEForAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (IS_STA_P2P_TYPE(prStaRec)) { + // TODO: + } + + } while (FALSE); + + return; + +} /* end of p2pGenerateP2P_IEForAssocReq() */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Probe Request frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pGenerateP2P_IEForProbeReq ( + IN P_ADAPTER_T prAdapter, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + ASSERT(prAdapter); + ASSERT(pucBuf); + + // TODO: + + return; + +} /* end of p2pGenerateP2P_IEForProbReq() */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pCalculateP2P_IELenForProbeReq ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) { + return 0; + } + + // TODO: + + return 0; + +} /* end of p2pCalculateP2P_IELenForProbeReq() */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indiate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pRunEventAAATxFail ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + P_BSS_INFO_T prBssInfo; + + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_UNSPECIFIED); + + + //20120830 moved into p2puUncDisconnect. + //cnmStaRecFree(prAdapter, prStaRec, TRUE); + + return; +} /* p2pRunEventAAATxFail */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indiate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +p2pRunEventAAAComplete ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + bssAddStaRecToClientList(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) { + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indiate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +p2pRunEventAAASuccess ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + /* Glue layer indication. */ + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, TRUE); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAASuccess */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +p2pRxPublicActionFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_P2P_PUBLIC_ACTION_FRAME_T prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + ASSERT(prSwRfb); + ASSERT(prAdapter); + + + + prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T)prSwRfb->pvHeader; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + DBGLOG(P2P, TRACE, ("RX Public Action Frame Token:%d.\n", prPublicActionFrame->ucDialogToken)); + + if (prPublicActionFrame->ucCategory != CATEGORY_PUBLIC_ACTION) { + return rWlanStatus; + } + + switch (prPublicActionFrame->ucAction) { + case ACTION_PUBLIC_WIFI_DIRECT: + break; + case ACTION_GAS_INITIAL_REQUEST: + case ACTION_GAS_INITIAL_RESPONSE: + case ACTION_GAS_COMEBACK_REQUEST: + case ACTION_GAS_COMEBACK_RESPONSE: + break; + default: + break; + } + + return rWlanStatus; +} /* p2pRxPublicActionFrame */ + + + +WLAN_STATUS +p2pRxActionFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_P2P_ACTION_FRAME_T prP2pActionFrame = (P_P2P_ACTION_FRAME_T)NULL; + UINT_8 aucOui[3] = VENDOR_OUI_WFA_SPECIFIC; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pActionFrame = (P_P2P_ACTION_FRAME_T)prSwRfb->pvHeader; + + if (prP2pActionFrame->ucCategory != CATEGORY_VENDOR_SPECIFIC_ACTION) { + DBGLOG(P2P, TRACE, ("RX Action Frame but not vendor specific.\n")); + break; + } + + + if ((prP2pActionFrame->ucOuiType != VENDOR_OUI_TYPE_P2P) || + (prP2pActionFrame->aucOui[0] != aucOui[0]) || + (prP2pActionFrame->aucOui[1] != aucOui[1]) || + (prP2pActionFrame->aucOui[2] != aucOui[2])) { + DBGLOG(P2P, TRACE, ("RX Vendor Specific Action Frame but not P2P Type or not WFA OUI.\n")); + break; + } + + } while (FALSE); + + return rWlanStatus; +} /* p2pRxActionFrame */ + + +VOID +p2pProcessEvent_UpdateNOAParam ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam + ) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_32 i; + BOOLEAN fgNoaAttrExisted = FALSE; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIndex]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + prP2pSpecificBssInfo->fgEnableOppPS = prEventUpdateNoaParam->fgEnableOppPS; + prP2pSpecificBssInfo->u2CTWindow = prEventUpdateNoaParam->u2CTWindow; + prP2pSpecificBssInfo->ucNoAIndex = prEventUpdateNoaParam->ucNoAIndex; + prP2pSpecificBssInfo->ucNoATimingCount = prEventUpdateNoaParam->ucNoATimingCount; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->fgEnableOppPS; + + + ASSERT(prP2pSpecificBssInfo->ucNoATimingCount <= P2P_MAXIMUM_NOA_COUNT); + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + // in used + prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse = + prEventUpdateNoaParam->arEventNoaTiming[i].fgIsInUse; + // count + prP2pSpecificBssInfo->arNoATiming[i].ucCount = + prEventUpdateNoaParam->arEventNoaTiming[i].ucCount; + // duration + prP2pSpecificBssInfo->arNoATiming[i].u4Duration = + prEventUpdateNoaParam->arEventNoaTiming[i].u4Duration; + // interval + prP2pSpecificBssInfo->arNoATiming[i].u4Interval = + prEventUpdateNoaParam->arEventNoaTiming[i].u4Interval; + // start time + prP2pSpecificBssInfo->arNoATiming[i].u4StartTime = + prEventUpdateNoaParam->arEventNoaTiming[i].u4StartTime; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse; + } + + prP2pSpecificBssInfo->fgIsNoaAttrExisted = fgNoaAttrExisted; + + // update beacon content by the change + bssUpdateBeaconContent(prAdapter, ucNetTypeIndex); +} + +#endif /* CFG_ENABLE_WIFI_DIRECT */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c new file mode 100755 index 000000000000..cd6f6e28542c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c @@ -0,0 +1,3845 @@ +#include "precomp.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + + +APPEND_VAR_ATTRI_ENTRY_T txAssocRspAttributesTable[] = { + { (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS) , NULL, p2pFuncAppendAttriStatusForAssocRsp } /* 0 */ // Status + ,{ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING), NULL, p2pFuncAppendAttriExtListenTiming } /* 8 */ +}; + + +APPEND_VAR_IE_ENTRY_T txProbeRspIETable[] = { + { (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE } /* 50 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE } /* 42 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE } /* 45 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE } /* 61 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE } /* 48 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE } /* 74 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE } /* 127 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE } /* 221 */ + ,{ (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE } /* 221 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for requesting scan. There is an option to do ACTIVE or PASSIVE scan. +* +* @param eScanType - Specify the scan type of the scan request. It can be an ACTIVE/PASSIVE +* Scan. +* eChannelSet - Specify the prefered channel set. +* A FULL scan would request a legacy full channel normal scan.(usually ACTIVE). +* A P2P_SOCIAL scan would scan 1+6+11 channels.(usually ACTIVE) +* A SPECIFIC scan would only 1/6/11 channels scan. (Passive Listen/Specific Search) +* ucChannelNum - A specific channel number. (Only when channel is specified) +* eBand - A specific band. (Only when channel is specified) +* +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncRequestScan ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo + ) +{ + + P_MSG_SCN_SCAN_REQ prScanReq = (P_MSG_SCN_SCAN_REQ)NULL; + + DEBUGFUNC("p2pFuncRequestScan()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prScanReqInfo != NULL)); + + if (prScanReqInfo->eChannelSet == SCAN_CHANNEL_SPECIFIED) { + ASSERT_BREAK(prScanReqInfo->ucNumChannelList > 0); + DBGLOG(P2P, LOUD, ("P2P Scan Request Channel:%d\n", prScanReqInfo->arScanChannelList[0].ucChannelNum)); + } + + prScanReq = (P_MSG_SCN_SCAN_REQ)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + if (!prScanReq) { + ASSERT(0); // Can't trigger SCAN FSM + break; + } + + prScanReq->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ; + prScanReq->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReq->ucNetTypeIndex = (UINT_8)NETWORK_TYPE_P2P_INDEX; + prScanReq->eScanType = prScanReqInfo->eScanType; + prScanReq->eScanChannel = prScanReqInfo->eChannelSet; + prScanReq->u2IELen = 0; + + /* Copy IE for Probe Request. */ + kalMemCopy(prScanReq->aucIE, prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReq->u2IELen = (UINT_16)prScanReqInfo->u4BufLength; + + prScanReq->u2ChannelDwellTime = prScanReqInfo->u2PassiveDewellTime; + + switch (prScanReqInfo->eChannelSet) { + case SCAN_CHANNEL_SPECIFIED: + { + UINT_32 u4Idx = 0; + P_RF_CHANNEL_INFO_T prDomainInfo = (P_RF_CHANNEL_INFO_T)prScanReqInfo->arScanChannelList; + + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) { + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + + for (u4Idx = 0; u4Idx < prScanReqInfo->ucNumChannelList; u4Idx++) { + prScanReq->arChnlInfoList[u4Idx].ucChannelNum = prDomainInfo->ucChannelNum; + prScanReq->arChnlInfoList[u4Idx].eBand = prDomainInfo->eBand; + prDomainInfo++; + } + + prScanReq->ucChannelListNum = prScanReqInfo->ucNumChannelList; + } + case SCAN_CHANNEL_FULL: + case SCAN_CHANNEL_2G4: + case SCAN_CHANNEL_P2P_SOCIAL: + { + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, + prScanReqInfo->rSsidStruct.ucSsidLen); + + /* For compatible. */ + if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, prScanReq->aucSSID, prScanReq->ucSSIDLength)) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + } + else if (prScanReq->ucSSIDLength != 0) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + } + break; + default: + /* Currently there is no other scan channel set. */ + ASSERT(FALSE); + break; + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prScanReq, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + + return; +} /* p2pFuncRequestScan */ + +VOID +p2pFuncCancelScan ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_SCAN_REQ_INFO_T prScanInfo + ) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanInfo != NULL)); + + if (!prScanInfo->fgIsScanRequest) { + break; + } + + + if (prScanInfo->ucSeqNumOfScnMsg) { + /* There is a channel privilege on hand. */ + DBGLOG(P2P, TRACE, ("P2P Cancel Scan\n")); + + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, ("Buffer not enough, can not cancel scan.\n")); + ASSERT(FALSE); + break; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->ucSeqNum = prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prScanCancelMsg, + MSG_SEND_METHOD_BUF); + + + } + + + } while (FALSE); + + return; +} /* p2pFuncCancelScan */ + + +VOID +p2pFuncSwitchOPMode ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN ENUM_OP_MODE_T eOpMode, + IN BOOLEAN fgSyncToFW + ) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pBssInfo != NULL) && + (eOpMode < OP_MODE_NUM)); + + if (prP2pBssInfo->eCurrentOPMode != eOpMode) { + DBGLOG(P2P, TRACE, ("p2pFuncSwitchOPMode: Switch to from %d, to %d.\n", prP2pBssInfo->eCurrentOPMode, eOpMode)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + + p2pFsmRunEventStopAP(prAdapter, NULL); + break; + default: + break; + } + + + prP2pBssInfo->eIntendOPMode = eOpMode; + prP2pBssInfo->eCurrentOPMode = eOpMode; + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + DBGLOG(P2P, TRACE, ("p2pFuncSwitchOPMode: Switch to Client.\n")); + case OP_MODE_ACCESS_POINT: +// if (!IS_BSS_ACTIVE(prP2pBssInfo)) { +// SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); +// nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); +// } + + /* Change interface address. */ + if (eOpMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, ("p2pFuncSwitchOPMode: Switch to AP.\n")); + prP2pBssInfo->ucSSIDLen = 0; + } + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucInterfaceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucInterfaceAddress); + + + break; + case OP_MODE_P2P_DEVICE: + { + /* Change device address. */ + DBGLOG(P2P, TRACE, ("p2pFuncSwitchOPMode: Switch back to P2P Device.\n")); + +// if (!IS_BSS_ACTIVE(prP2pBssInfo)) { +// SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); +// nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); +// } + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + + } + break; + default: +// if (IS_BSS_ACTIVE(prP2pBssInfo)) { +// UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + +// nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); +// } + ASSERT(FALSE); + break; + } + + if (1) { + P2P_DISCONNECT_INFO rP2PDisInfo; + + rP2PDisInfo.ucRole = 2; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_P2P_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(P2P_DISCONNECT_INFO), + (PUINT_8)&rP2PDisInfo, + NULL, + 0); + } + + + DBGLOG(P2P, TRACE, ("The device address is changed to " MACSTR " \n", MAC2STR(prP2pBssInfo->aucOwnMacAddr))); + DBGLOG(P2P, TRACE, ("The BSSID is changed to " MACSTR " \n", MAC2STR(prP2pBssInfo->aucBSSID))); + + /* Update BSS INFO to FW. */ + if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) { + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + } + + } while (FALSE); + + return; +} /* p2pFuncSwitchOPMode */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will start a P2P Group Owner and send Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncStartGO ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucSsidBuf, + IN UINT_8 ucSsidLen, + IN UINT_8 ucChannelNum, + IN ENUM_BAND_T eBand, + IN ENUM_CHNL_EXT_T eSco, + IN BOOLEAN fgIsPureAP + ) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + + DBGLOG(P2P, TRACE, ("p2pFuncStartGO:\n")); + + /* AP mode started. */ + p2pFuncSwitchOPMode(prAdapter, prBssInfo, prBssInfo->eIntendOPMode, FALSE); + + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + //4 <1.1> Assign SSID + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + pucSsidBuf, + ucSsidLen); + + DBGLOG(P2P, TRACE, ("GO SSID:%s \n", prBssInfo->aucSSID)); + + //4 <1.2> Clear current AP's STA_RECORD_T and current AID + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + prBssInfo->u2AssocId = 0; + + + //4 <1.3> Setup Channel, Band and Phy Attributes + prBssInfo->ucPrimaryChannel = ucChannelNum; + prBssInfo->eBand = eBand; + prBssInfo->eBssSCO = eSco; + + DBGLOG(P2P, TRACE, ("GO Channel:%d \n", ucChannelNum)); + + + if (prBssInfo->eBand == BAND_5G) { + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN); /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } + else if (fgIsPureAP) { + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN); /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } + else { + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN); /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } + + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + if (prBssInfo->ucAllSupportedRatesLen == 0) { + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); + } + + //4 <1.5> Setup MIB for current BSS + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + + //3 <2> Update BSS_INFO_T common part +#if CFG_SUPPORT_AAA + if (!fgIsPureAP) { + prBssInfo->fgIsProtection = TRUE; /* Always enable protection at P2P GO */ + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); + } + else { + if (kalP2PGetCipher(prAdapter->prGlueInfo)) + prBssInfo->fgIsProtection = TRUE; + } + + // 20120106 frog: I want separate OP_Mode & Beacon TX Function. + //p2pFuncSwitchOPMode(prAdapter, prBssInfo, OP_MODE_ACCESS_POINT, FALSE); + + bssInitForAP(prAdapter, prBssInfo, FALSE); + + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_P2P_INDEX); +#endif /* CFG_SUPPORT_AAA */ + + + //3 <3> Set MAC HW + //4 <3.1> Setup channel and bandwidth + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + //4 <3.2> Reset HW TSF Update Mode and Beacon Mode + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + //4 <3.3> Update Beacon again for network phy type confirmed. + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + //4 <3.4> Setup BSSID + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + + } while (FALSE); + + return; +} /* p2pFuncStartGO() */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncReleaseCh ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ) +{ + P_MSG_CH_ABORT_T prMsgChRelease = (P_MSG_CH_ABORT_T)NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) { + break; + } + else { + DBGLOG(P2P, TRACE, ("P2P Release Channel\n")); + prChnlReqInfo->fgIsChannelRequested = FALSE; + } + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (P_MSG_CH_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChRelease) { + ASSERT(0); // Can't release Channel to CNM + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChRelease, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + + return; +} /* p2pFuncReleaseCh */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncAcquireCh ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ) +{ + P_MSG_CH_REQ_T prMsgChReq = (P_MSG_CH_REQ_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); // Can't indicate CNM for channel acquiring + break; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + + kalMemZero(prMsgChReq->aucBSSID, MAC_ADDR_LEN); + + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgChReq, + MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); + + return; +} /* p2pFuncAcquireCh */ + +#if 0 +WLAN_STATUS +p2pFuncBeaconUpdate( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBcnHdr, + IN UINT_32 u4HdrLen, + IN PUINT_8 pucBcnBody, + IN UINT_32 u4BodyLen, + IN UINT_32 u4DtimPeriod, + IN UINT_32 u4BcnInterval) +{ + WLAN_STATUS rResultStatus = WLAN_STATUS_INVALID_DATA; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T)NULL; + PUINT_8 pucTIMBody = (PUINT_8)NULL; + UINT_16 u2FrameLength = 0, UINT_16 u2OldBodyLen = 0; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prBcnMsduInfo = prP2pBssInfo->prBeacon + + ASSERT_BREAK(prBcnMsduInfo != NULL); + + /* TODO: Find TIM IE pointer. */ + prBcnFrame = prBcnMsduInfo->prPacket; + + ASSERT_BREAK(prBcnFrame != NULL); + + do { + /* Ori header. */ + UINT_16 u2IELength = 0, u2Offset = 0; + PUINT_8 pucIEBuf = prBcnFrame->aucInfoElem; + + u2IELength = prBcnMsduInfo->u2FrameLength - prBcnMsduInfo->ucMacHeaderLength; + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + if ((IE_ID(pucIEBuf) == ELEM_ID_TIM) || + ((IE_ID(pucIEBuf) > ELEM_ID_IBSS_PARAM_SET)) { + pucTIMBody = pucIEBuf; + break + } + u2FrameLength += IE_SIZE(pucIEBuf); + } + + if (pucTIMBody == NULL) { + pucTIMBody = pucIEBuf; + } + + /* Body not change. */ + u2OldBodyLen = (UINT_16)((UINT_32)pucTIMBody - (UINT_32)prBcnFrame->aucInfoElem); + + // Move body. + kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); + } while (FALSE); + + + if (pucBcnHdr) { + kalMemCopy(prBcnMsduInfo->prPacket, pucBcnHdr, u4HdrLen); + + pucTIMBody = (PUINT_8)((UINT_32)prBcnMsduInfo->prPacket + u4HdrLen); + + prBcnMsduInfo->ucMacHeaderLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + + u2FrameLength = u4HdrLen; /* Header + Partial Body. */ + + } + else { + /* Header not change. */ + u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; + } + + + if (pucBcnBody) { + kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); + u2FrameLength += (UINT_16)u4BodyLen; + } + else { + kalMemCopy(pucTIMBody, aucIEBuf, u2OldBodyLen); + u2FrameLength += u2OldBodyLen; + } + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = u2FrameLength; + + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + prP2pBssInfo->u2BeaconInterval = (UINT_16)u4BcnInterval; + prP2pBssInfo->ucDTIMPeriod = (UINT_8)u4DtimPeriod; + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + prBcnMsduInfo->ucPacketType = 3; + + rResultStatus = nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prP2pBssInfo->u2CapInfo, + (PUINT_8)prBcnFrame->aucInfoElem, + prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); + + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* AP is created, Beacon Update. */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } while (FALSE); + + return rResultStatus; +} /* p2pFuncBeaconUpdate */ + +#else +WLAN_STATUS +p2pFuncBeaconUpdate ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, + IN PUINT_8 pucNewBcnHdr, + IN UINT_32 u4NewHdrLen, + IN PUINT_8 pucNewBcnBody, + IN UINT_32 u4NewBodyLen + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T)NULL; + P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T)NULL; + PUINT_8 pucIEBuf = (PUINT_8)NULL; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pBssInfo != NULL) && + (prBcnUpdateInfo != NULL)); + + prBcnMsduInfo = prP2pBssInfo->prBeacon; + +#if DBG + if (prBcnUpdateInfo->pucBcnHdr != NULL) { + ASSERT((UINT_32)prBcnUpdateInfo->pucBcnHdr == ((UINT_32)prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD)); + } + + if (prBcnUpdateInfo->pucBcnBody != NULL) { + ASSERT((UINT_32)prBcnUpdateInfo->pucBcnBody == ((UINT_32)prBcnUpdateInfo->pucBcnHdr + (UINT_32)prBcnUpdateInfo->u4BcnHdrLen)); + } +#endif + prBcnFrame = (P_WLAN_BEACON_FRAME_T)((UINT_32)prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD); + + if (!pucNewBcnBody) { + /* Old body. */ + pucNewBcnBody = prBcnUpdateInfo->pucBcnBody; + ASSERT(u4NewBodyLen == 0); + u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen; + } + else { + prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen; + } + + /* Temp buffer body part. */ + kalMemCopy(aucIEBuf, pucNewBcnBody, u4NewBodyLen); + + if (pucNewBcnHdr) { + kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen); + prBcnUpdateInfo->pucBcnHdr = (PUINT_8)prBcnFrame; + prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; + } + + pucIEBuf = (PUINT_8)((UINT_32)prBcnUpdateInfo->pucBcnHdr + (UINT_32)prBcnUpdateInfo->u4BcnHdrLen); + kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen); + prBcnUpdateInfo->pucBcnBody = pucIEBuf; + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (UINT_16)(prBcnUpdateInfo->u4BcnHdrLen + prBcnUpdateInfo->u4BcnBodyLen); + + prBcnMsduInfo->ucPacketType = 3; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + + /* Update BSS INFO related information. */ + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prBcnFrame->aucSrcAddr); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prBcnFrame->aucBSSID); + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + + p2pFuncParseBeaconContent(prAdapter, + prP2pBssInfo, + (PUINT_8)prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); + +#if 1 + //bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); +#else + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBcnFrame->u2CapInfo, + (PUINT_8)prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); +#endif + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncBeaconUpdate */ + +#endif + +// TODO: We do not apply IE in deauth frame set from upper layer now. +WLAN_STATUS +p2pFuncDeauth ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2IELen, + IN BOOLEAN fgSendDeauth + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, + NETWORK_TYPE_P2P_INDEX, + pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T)NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((UINT_32)prCliStaRec == (UINT_32)prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) { + break; + } + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) { + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDeauth, u2ReasonCode); + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDeauth */ + +// TODO: We do not apply IE in disassoc frame set from upper layer now. +WLAN_STATUS +p2pFuncDisassoc ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2IELen, + IN BOOLEAN fgSendDisassoc + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, + NETWORK_TYPE_P2P_INDEX, + pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T)NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((UINT_32)prCliStaRec == (UINT_32)prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + //p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) { + break; + } + + //p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) { + + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); + //20120830 moved into p2pFuncDisconnect(). + //cnmStaRecFree(prAdapter, prCliStaRec, TRUE); + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDissolve ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN BOOLEAN fgSendDeauth, + IN UINT_16 u2ReasonCode + ) +{ + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + NULL, + 0, + REASON_CODE_DEAUTH_LEAVING_BSS); + + // 2012/02/14 frog: After formation before join group, prStaRecOfAP is NULL. + p2pFuncDisconnect(prAdapter, + prP2pBssInfo->prStaRecOfAP, + fgSendDeauth, + u2ReasonCode); + } + + /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). hit prStaRecOfAP == NULL. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + prP2pBssInfo->prStaRecOfAP = NULL; + + break; + case OP_MODE_ACCESS_POINT: + /* Under AP mode, we would net send deauthentication frame to each STA. + * We only stop the Beacon & let all stations timeout. + */ + { + P_LINK_T prStaRecOfClientList = (P_LINK_T)NULL; + + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + NULL, + (P_SW_RFB_T)NULL, + u2ReasonCode, + (PFN_TX_DONE_HANDLER)NULL); + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + while (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_REMOVE_HEAD(prStaRecOfClientList, prCurrStaRec, P_STA_RECORD_T); + + /* Indicate to Host. */ + //kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); + + p2pFuncDisconnect(prAdapter, prCurrStaRec, TRUE, u2ReasonCode); + + } + + } + + break; + default: + return; // 20110420 -- alreay in Device Mode. + } + + /* Make the deauth frame send to FW ASAP. */ + wlanAcquirePowerControl(prAdapter); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + wlanReleasePowerControl(prAdapter); + + kalMdelay(100); + + /* Change Connection Status. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + } while (FALSE); + + return; +} /* p2pFuncDissolve */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDisconnect ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN BOOLEAN fgSendDeauth, + IN UINT_16 u2ReasonCode + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + DBGLOG(P2P, TRACE, ("p2pFuncDisconnect()")); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + // TODO: +// kalP2PGOStationUpdate +// kalP2PGCIndicateConnectionStatus + //p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, prStaRec->aucMacAddr); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); + } + + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prStaRec, + (P_SW_RFB_T)NULL, + u2ReasonCode, + (PFN_TX_DONE_HANDLER)p2pFsmRunEventDeauthTxDone); + } + else { + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { + DBGLOG(P2P, TRACE, ("No More Client, Media Status DISCONNECTED\n")); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + } + + if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + /* GO: It would stop Beacon TX. GC: Stop all BSS related PS function. */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + } + + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + + + + + + +WLAN_STATUS +p2pFuncTxMgmtFrame ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, + IN P_MSDU_INFO_T prMgmtTxMsdu, + IN UINT_64 u8Cookie + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + // 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL + /* Packet on driver, not done yet, drop it. */ + if ((prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu) != NULL) { + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, + (UINT_32)prTxMsduInfo->u2FrameLength); + + // Leave it to TX Done handler. + //cnmMgtPktFree(prAdapter, prTxMsduInfo); + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + // 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL + /* Packet transmitted, wait tx done. (cookie issue) */ + // 20120105 frog - use another u8cookie to store this value. + + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + + + prWlanHdr = (P_WLAN_MAC_HEADER_T)((UINT_32)prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, prWlanHdr->aucAddr1); + prMgmtTxMsdu->ucNetworkType = (UINT_8)NETWORK_TYPE_P2P_INDEX; + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, ("p2pFuncTxMgmtFrame: TX MAC_FRAME_PROBE_RSP\n")); + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, prMgmtTxMsdu); + break; + default: + break; + } + + + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; + prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL)?(prStaRec->ucIndex):(0xFF); + if (prStaRec != NULL) { + DBGLOG(P2P, TRACE, ("Mgmt with station record: "MACSTR" .\n", MAC2STR(prStaRec->aucMacAddr))); + } + + prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; // TODO: undcertain. + prMgmtTxMsdu->fgIs802_1x = FALSE; + prMgmtTxMsdu->fgIs802_11 = TRUE; + prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMgmtTxMsdu->pfTxDoneHandler = p2pFsmRunEventMgmtFrameTxDone; + prMgmtTxMsdu->fgIsBasicRate = TRUE; + DBGLOG(P2P, TRACE, ("Mgmt seq NO. %d .\n", prMgmtTxMsdu->ucTxSeqNum)); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + + + +VOID +p2pFuncSetChannel ( + IN P_ADAPTER_T prAdapter, + IN P_RF_CHANNEL_INFO_T prRfChannelInfo + ) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnSettings->ucOperatingChnl = prRfChannelInfo->ucChannelNum; + prP2pConnSettings->eBand = prRfChannelInfo->eBand; + + + } while (FALSE); + + return; +} +/* p2pFuncSetChannel */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncRetryJOIN ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_P2P_JOIN_INFO_T prJoinInfo + ) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T)NULL; + BOOLEAN fgRetValue = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prStaRec != NULL) && + (prJoinInfo != NULL)); + + /* Retry other AuthType if possible */ + if (!prJoinInfo->ucAvailableAuthTypes) { + break; + } + + if (prJoinInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, INFO, ("RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n")); + + prJoinInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_SHARED_KEY; + } + else { + DBGLOG(P2P, ERROR, ("RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n")); + ASSERT(0); + break; + } + + prJoinInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + ASSERT(0); // Can't trigger SAA FSM + break; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + + fgRetValue = TRUE; + } while (FALSE); + + return fgRetValue; + + + +}/* end of p2pFuncRetryJOIN() */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncUpdateBssInfoForJOIN ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prAssocRspSwRfb + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T)NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + + DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + DBGLOG(P2P, INFO, ("Update P2P_BSS_INFO_T and apply settings to MAC\n")); + + //3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings + //4 <1.1> Setup Operation Mode + prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + //4 <1.2> Setup SSID + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen); + + if (prBssDesc == NULL) { + /* Target BSS NULL. */ + DBGLOG(P2P, TRACE,("Target BSS NULL\n")); + return; + } + + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAssocRspFrame->aucBSSID)) { + ASSERT(FALSE); + } + + //4 <1.3> Setup Channel, Band + prP2pBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + prP2pBssInfo->eBand = prBssDesc->eBand; + + + //3 <2> Update BSS_INFO_T from STA_RECORD_T + //4 <2.1> Save current AP's STA_RECORD_T and current AID + prP2pBssInfo->prStaRecOfAP = prStaRec; + prP2pBssInfo->u2AssocId = prStaRec->u2AssocId; + + //4 <2.2> Setup Capability + prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ + + if (prP2pBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { + prP2pBssInfo->fgIsShortPreambleAllowed = TRUE; + } + else { + prP2pBssInfo->fgIsShortPreambleAllowed = FALSE; + } + + //4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set + prP2pBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prP2pBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prP2pBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prP2pBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + + //3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) + //4 <3.1> Setup BSSID + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + + //4 <3.2> Parse WMM and setup QBSS flag + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prP2pBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + //3 <4> Update BSS_INFO_T from BSS_DESC_T + ASSERT(prBssDesc); + + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + //4 <4.1> Setup MIB for current BSS + prP2pBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prP2pBssInfo->ucDTIMPeriod = 0; + prP2pBssInfo->u2ATIMWindow = 0; + + prP2pBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + + //4 <4.2> Update HT information and set channel + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + //4 <4.3> Sync with firmware for BSS-INFO + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + //4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked + //inside scanProcessBeaconAndProbeResp() after 1st beacon is received + + return; +} /* end of p2pUpdateBssInfoForJOIN() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncValidateAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PP_STA_RECORD_T pprStaRec, + OUT PUINT_16 pu2StatusCode + ) +{ + BOOLEAN fgReplyAuth = TRUE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T)NULL; + + DBGLOG(P2P, TRACE, ("p2pValidate Authentication Frame\n")) + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prSwRfb != NULL) && + (pprStaRec != NULL) && + (pu2StatusCode != NULL)); + + /* P2P 3.2.8 */ + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAuthFrame = (P_WLAN_AUTH_FRAME_T)prSwRfb->pvHeader; + + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + /* We are not under AP Mode yet. */ + fgReplyAuth = FALSE; + DBGLOG(P2P, WARN, ("Current OP mode is not under AP mode. (%d)\n", prP2pBssInfo->eCurrentOPMode)); + break; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_P2P_INDEX, + prAuthFrame->aucSrcAddr); + + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, + (UINT_8) NETWORK_TYPE_P2P_INDEX); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + /* Sent a message event to clean un-used STA_RECORD_T. */ + ASSERT(prStaRec); + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + prStaRec->u2BSSBasicRateSet = prP2pBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = RATE_SET_ERP_P2P; + + prStaRec->u2OperationalRateSet = RATE_SET_ERP_P2P; + prStaRec->ucPhyTypeSet = PHY_TYPE_SET_802_11GN; + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + } + + } + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + /* GROUP limit full. */ + /* P2P 3.2.8 */ + DBGLOG(P2P, WARN, ("Group Limit Full. (%d)\n", (INT_16)prP2pBssInfo->rStaRecOfClientList.u4NumElem)); + cnmStaRecFree(prAdapter, prStaRec, FALSE); + break; + } + else { + /* Hotspot Blacklist */ + if(prAuthFrame->aucSrcAddr) { + if(kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr)) { + fgReplyAuth = FALSE; + return fgReplyAuth; + } + } + } + + //prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; + prStaRec->eStaType = STA_TYPE_P2P_GC; + + prStaRec->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + prStaRec->ucJoinFailureCount = 0; + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + + return fgReplyAuth; + +} /* p2pFuncValidateAuth */ + + + + +VOID +p2pFuncResetStaRecStatus ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + ASSERT(FALSE); + break; + } + + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); + + return; +} /* p2pFuncResetStaRecStatus */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to initialize the value of the connection settings for +* P2P network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncInitConnectionSettings ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings + ) +{ + P_DEVICE_TYPE_T prDevType; + UINT_8 aucDefaultDevName[] = P2P_DEFAULT_DEV_NAME; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(prP2PConnSettings); + + /* Setup Default Device Name */ + prP2PConnSettings->ucDevNameLen = P2P_DEFAULT_DEV_NAME_LEN; + kalMemCopy(prP2PConnSettings->aucDevName, aucDefaultDevName, sizeof(aucDefaultDevName)); + + /* Setup Primary Device Type (Big-Endian) */ + prDevType = &prP2PConnSettings->rPrimaryDevTypeBE; + + prDevType->u2CategoryId = HTONS(P2P_DEFAULT_PRIMARY_CATEGORY_ID); + prDevType->u2SubCategoryId = HTONS(P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID); + + prDevType->aucOui[0] = aucWfaOui[0]; + prDevType->aucOui[1] = aucWfaOui[1]; + prDevType->aucOui[2] = aucWfaOui[2]; + prDevType->aucOui[3] = VENDOR_OUI_TYPE_WPS; + + /* Setup Secondary Device Type */ + prP2PConnSettings->ucSecondaryDevTypeCount = 0; + + /* Setup Default Config Method */ + prP2PConnSettings->eConfigMethodSelType = ENUM_CONFIG_METHOD_SEL_AUTO; + prP2PConnSettings->u2ConfigMethodsSupport = P2P_DEFAULT_CONFIG_METHOD; + prP2PConnSettings->u2TargetConfigMethod = 0; + prP2PConnSettings->u2LocalConfigMethod = 0; + prP2PConnSettings->fgIsPasswordIDRdy = FALSE; + + /* For Device Capability */ + prP2PConnSettings->fgSupportServiceDiscovery = FALSE; + prP2PConnSettings->fgSupportClientDiscoverability = TRUE; + prP2PConnSettings->fgSupportConcurrentOperation = TRUE; + prP2PConnSettings->fgSupportInfraManaged = FALSE; + prP2PConnSettings->fgSupportInvitationProcedure = FALSE; + + /* For Group Capability */ +#if CFG_SUPPORT_PERSISTENT_GROUP + prP2PConnSettings->fgSupportPersistentP2PGroup = TRUE; +#else + prP2PConnSettings->fgSupportPersistentP2PGroup = FALSE; +#endif + prP2PConnSettings->fgSupportIntraBSSDistribution = TRUE; + prP2PConnSettings->fgSupportCrossConnection = TRUE; + prP2PConnSettings->fgSupportPersistentReconnect = FALSE; + + prP2PConnSettings->fgSupportOppPS = FALSE; + prP2PConnSettings->u2CTWindow = P2P_CTWINDOW_DEFAULT; + + /* For Connection Settings. */ + prP2PConnSettings->eAuthMode = AUTH_MODE_OPEN; + + prP2PConnSettings->prTargetP2pDesc = NULL; + prP2PConnSettings->ucSSIDLen = 0; + + /* Misc */ + prP2PConnSettings->fgIsScanReqIssued = FALSE; + prP2PConnSettings->fgIsServiceDiscoverIssued = FALSE; + prP2PConnSettings->fgP2pGroupLimit = FALSE; + prP2PConnSettings->ucOperatingChnl = 0; + prP2PConnSettings->ucListenChnl = 0; + prP2PConnSettings->ucTieBreaker = (UINT_8)(kalRandomNumber() & 0x1); + + prP2PConnSettings->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; + + return; +} /* p2pFuncInitConnectionSettings */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncValidateAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_16 pu2StatusCode + ) +{ + BOOLEAN fgReplyAssocResp = TRUE; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + P_WFD_ATTRIBUTE_T prWfdAttribute = (P_WFD_ATTRIBUTE_T)NULL; + BOOLEAN fgNeedFree = FALSE; +#endif + + + /* TODO(Kevin): Call P2P functions to check .. + 2. Check we can accept connection from thsi peer + a. If we are in PROVISION state, only accept the peer we do the GO formation previously. + b. If we are in OPERATION state, only accept the other peer when P2P_GROUP_LIMIT is 0. + 3. Check Black List here. + */ + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prSwRfb != NULL) && + (pu2StatusCode != NULL)); + + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T)prSwRfb->pvHeader; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready while RX AUTH frame. */ + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + else { + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + } + + prStaRec->u2DesiredNonHTRateSet &= prP2pBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prP2pBssInfo->ucPhyTypeSet; + + if (prStaRec->ucDesiredPhyTypeSet == 0) { + /* The station only support 11B rate. */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + +#if CFG_SUPPORT_WFD && 1 + //LOG_FUNC("Skip check WFD IE becasue some API is not ready\n"); /* Eddie */ + if (!prAdapter->rWifiVar.prP2pFsmInfo) { + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + DBGLOG(P2P, INFO,("Current WfdCfgSettings wfd_en %u wfd_info 0x%x wfd_policy 0x%x wfd_flag 0x%x\n", + prWfdCfgSettings->ucWfdEnable, prWfdCfgSettings->u2WfdDevInfo, + prWfdCfgSettings->u4WfdPolicy, prWfdCfgSettings->u4WfdFlag)); /* Eddie */ + if (prWfdCfgSettings->ucWfdEnable) { + if (prWfdCfgSettings->u4WfdPolicy & BIT(6)) { + /* Rejected all. */ + break; + } + else { + + //UINT_16 u2AttriListLen = 0; + UINT_16 u2WfdDevInfo = 0; + P_WFD_DEVICE_INFORMATION_IE_T prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T)NULL; + + //fgNeedFree = p2pFuncGetAttriList(prAdapter, + // VENDOR_OUI_TYPE_WFD, + // (PUINT_8)prAssocReqFrame->aucInfoElem, + // (prSwRfb->u2PacketLen - OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), + // (PPUINT_8)&prWfdAttribute, + // &u2AttriListLen); + + prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) + p2pFuncGetSpecAttri(prAdapter, + VENDOR_OUI_TYPE_WFD, + (PUINT_8)prAssocReqFrame->aucInfoElem, + (prSwRfb->u2PacketLen - OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), + WFD_ATTRI_ID_DEV_INFO); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(5)) && (prAttriWfdDevInfo != NULL)) { + /* Rejected with WFD IE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(0)) && (prAttriWfdDevInfo == NULL)) { + /* Rejected without WFD IE. */ + break; + } + + if (prAttriWfdDevInfo != NULL) { + + //prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T)p2pFuncGetSpecAttri(prAdapter, + // VENDOR_OUI_TYPE_WFD, + // (PUINT_8)prWfdAttribute, + // u2AttriListLen, + // WFD_ATTRI_ID_DEV_INFO); + //if (prAttriWfdDevInfo == NULL) { + // /* No such attribute. */ + // break; + //} + + WLAN_GET_FIELD_BE16(&prAttriWfdDevInfo->u2WfdDevInfo, &u2WfdDevInfo); + DBGLOG(P2P, INFO,("RX Assoc Req WFD Info:0x%x.\n", u2WfdDevInfo)); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(1)) && ((u2WfdDevInfo & 0x3) == 0x0)) { + /* Rejected because of SOURCE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(2)) && ((u2WfdDevInfo & 0x3) == 0x1)) { + /* Rejected because of Primary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(3)) && ((u2WfdDevInfo & 0x3) == 0x2)) { + /* Rejected because of Secondary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(4)) && ((u2WfdDevInfo & 0x3) == 0x3)) { + /* Rejected because of Source & Primary Sink. */ + break; + } + + /* Check role */ + + if(prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) { + + if((prWfdCfgSettings->u2WfdDevInfo & BITS(0,1)) == 0x3) { + //P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; + UINT_16 u2DevInfo = prWfdCfgSettings->u2WfdDevInfo; + + /* We may change role here if we are dual role */ + + if((u2WfdDevInfo & BITS(0,1)) == 0x00 /* Peer is Source*/) { + DBGLOG(P2P, INFO,("WFD: Switch role to primary sink\n")); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0,1); + prWfdCfgSettings->u2WfdDevInfo |= 0x1; + + /* event to annonce the role is chanaged to P-Sink */ + + } + else if((u2WfdDevInfo & BITS(0,1)) == 0x01 /* Peer is P-Sink */) { + + DBGLOG(P2P, INFO,("WFD: Switch role to source\n")); + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0,1); + /* event to annonce the role is chanaged to Source */ + } + else { + + DBGLOG(P2P, INFO,("WFD: Peer role is wrong type(dev 0x%x)\n", (u2DevInfo))); + DBGLOG(P2P, INFO,("WFD: Switch role to source\n")); + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0,1); + /* event to annonce the role is chanaged to Source */ + } + + p2pFsmRunEventWfdSettingUpdate (prAdapter,NULL); + + } /* Dual role p2p->wfd_params->WfdDevInfo */ + } /* WFD_FLAG_DEV_INFO_VALID */ + + + } + else { + /* Without WFD IE. + * Do nothing. Accept the connection request. + */ + } + } + + } /* ucWfdEnable */ + +#endif + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + +#if CFG_SUPPORT_WFD + if ((prWfdAttribute) && (fgNeedFree)) { + kalMemFree(prWfdAttribute, VIR_MEM_TYPE, WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE); + } +#endif + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the P2P IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncParseCheckForP2PInfoElem ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, + OUT PUINT_8 pucOuiType + ) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + P_IE_WFA_T prWfaIE = (P_IE_WFA_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pucOuiType != NULL)); + + prWfaIE = (P_IE_WFA_T)pucBuf; + + if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { + break; + } + else if (prWfaIE->aucOui[0] != aucWfaOui[0] || + prWfaIE->aucOui[1] != aucWfaOui[1] || + prWfaIE->aucOui[2] != aucWfaOui[2]) { + break; + } + + *pucOuiType = prWfaIE->ucOuiType; + + return TRUE; + } while (FALSE); + + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncValidateProbeReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT PUINT_32 pu4ControlFlags + ) +{ + BOOLEAN fgIsReplyProbeRsp = FALSE; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + DBGLOG(P2P, TRACE, ("p2pFuncValidateProbeReq\n")); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ) { + + printk("p2pFuncValidateProbeReq\n"); + + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return fgIsReplyProbeRsp; + +} /* end of p2pFuncValidateProbeReq() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncValidateRxActionFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + + + + +BOOLEAN +p2pFuncIsAPMode ( + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ) +{ + if (prP2pFsmInfo) { + return prP2pFsmInfo->fgIsApMode; + } + else { + return FALSE; + } +} +/* p2pFuncIsAPMode */ + + + +VOID +p2pFuncParseBeaconContent ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN PUINT_8 pucIEInfo, + IN UINT_32 u4IELen + ) +{ + PUINT_8 pucIE = (PUINT_8)NULL; + UINT_16 u2Offset = 0; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + BOOL ucNewSecMode = FALSE; + BOOL ucOldSecMode = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pBssInfo != NULL)); + + if (u4IELen == 0) { + break; + } + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pSpecificBssInfo->u2AttributeLen = 0; + + ASSERT_BREAK(pucIEInfo != NULL); + + pucIE = pucIEInfo; + + ucOldSecMode = kalP2PGetCipher(prAdapter->prGlueInfo); + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: /* 0 */ /* V */ /* Done */ + { + DBGLOG(P2P, TRACE, ("SSID update\n")); + + /* Update when starting GO. */ + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + + COPY_SSID(prP2pSpecificBssInfo->aucGroupSsid, + prP2pSpecificBssInfo->u2GroupSsidLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + + } + break; + case ELEM_ID_SUP_RATES: /* 1 */ /* V */ /* Done */ + { + DBGLOG(P2P, TRACE, ("Support Rate IE\n")); + kalMemCopy(prP2pBssInfo->aucAllSupportedRates, + SUP_RATES_IE(pucIE)->aucSupportedRates, + SUP_RATES_IE(pucIE)->ucLength); + + prP2pBssInfo->ucAllSupportedRatesLen = SUP_RATES_IE(pucIE)->ucLength; + + DBGLOG_MEM8(P2P, TRACE, SUP_RATES_IE(pucIE)->aucSupportedRates, SUP_RATES_IE(pucIE)->ucLength); + } + break; + case ELEM_ID_DS_PARAM_SET: /* 3 */ /* V */ /* Done */ + { + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, ("DS PARAM IE\n")); + + ASSERT(prP2pConnSettings->ucOperatingChnl == DS_PARAM_IE(pucIE)->ucCurrChnl); + + if (prP2pConnSettings->eBand != BAND_2G4) { + ASSERT(FALSE); + break; + } + + //prP2pBssInfo->ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + + //prP2pBssInfo->eBand = BAND_2G4; + } + break; + case ELEM_ID_TIM: /* 5 */ /* V */ + DBGLOG(P2P, TRACE, ("TIM IE\n")); + TIM_IE(pucIE)->ucDTIMPeriod = prP2pBssInfo->ucDTIMPeriod; + break; + case ELEM_ID_ERP_INFO: /* 42 */ /* V */ + { +#if 1 + /* This IE would dynamic change due to FW detection change is required. */ + DBGLOG(P2P, TRACE, ("ERP IE will be over write by driver\n")); + DBGLOG(P2P, TRACE, (" ucERP: %x. \n", ERP_INFO_IE(pucIE)->ucERP)); + +#else + /* This IE would dynamic change due to FW detection change is required. */ + DBGLOG(P2P, TRACE, ("ERP IE.\n")); + + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11GN; + + ASSERT(prP2pBssInfo->eBand == BAND_2G4); + + prP2pBssInfo->fgObssErpProtectMode = ((ERP_INFO_IE(pucIE)->ucERP & ERP_INFO_USE_PROTECTION)? TRUE : FALSE); + + prP2pBssInfo->fgErpProtectMode = ((ERP_INFO_IE(pucIE)->ucERP & (ERP_INFO_USE_PROTECTION | ERP_INFO_NON_ERP_PRESENT))? TRUE : FALSE); +#endif + + } + break; + case ELEM_ID_HT_CAP: /* 45 */ /* V */ + { +#if 1 + DBGLOG(P2P, TRACE, ("HT CAP IE would be overwritten by driver\n")); + + DBGLOG(P2P, TRACE, ("HT Cap Info:%x, AMPDU Param:%x\n", HT_CAP_IE(pucIE)->u2HtCapInfo, HT_CAP_IE(pucIE)->ucAmpduParam)); + + DBGLOG(P2P, TRACE, ("HT Extended Cap Info:%x, TX Beamforming Cap Info:%lx, Ant Selection Cap Info%x \n", + HT_CAP_IE(pucIE)->u2HtExtendedCap, + HT_CAP_IE(pucIE)->u4TxBeamformingCap, + HT_CAP_IE(pucIE)->ucAselCap)); +#else + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + + /* u2HtCapInfo */ + if ((HT_CAP_IE(pucIE)->u2HtCapInfo & + (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M)) == 0) { + prP2pBssInfo->fgAssoc40mBwAllowed = FALSE; + } + else { + prP2pBssInfo->fgAssoc40mBwAllowed = TRUE; + } + + if ((HT_CAP_IE(pucIE)->u2HtCapInfo & + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M)) == 0) { + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; + } + else { + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = FALSE; + } + + /* ucAmpduParam */ + DBGLOG(P2P, TRACE, ("AMPDU setting from supplicant:0x%x, & default value:0x%x\n", (UINT_8)HT_CAP_IE(pucIE)->ucAmpduParam, (UINT_8)AMPDU_PARAM_DEFAULT_VAL)); + + /* rSupMcsSet */ + /* Can do nothing. the field is default value from other configuration. */ + //HT_CAP_IE(pucIE)->rSupMcsSet; + + /* u2HtExtendedCap */ + ASSERT(HT_CAP_IE(pucIE)->u2HtExtendedCap == (HT_EXT_CAP_DEFAULT_VAL & ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE))); + + /* u4TxBeamformingCap */ + ASSERT(HT_CAP_IE(pucIE)->u4TxBeamformingCap == TX_BEAMFORMING_CAP_DEFAULT_VAL); + + /* ucAselCap */ + ASSERT(HT_CAP_IE(pucIE)->ucAselCap == ASEL_CAP_DEFAULT_VAL); +#endif + } + break; + case ELEM_ID_RSN: /* 48 */ /* V */ + { + RSN_INFO_T rRsnIe; + + DBGLOG(P2P, TRACE, ("RSN IE\n")); + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); + ucNewSecMode = TRUE; + + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &rRsnIe)) { + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + prP2pBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; + prP2pBssInfo->u2RsnSelectedCapInfo = rRsnIe.u2RsnCap; + } + } + break; + case ELEM_ID_EXTENDED_SUP_RATES: /* 50 */ /* V */ + /* Be attention, ELEM_ID_SUP_RATES should be placed before ELEM_ID_EXTENDED_SUP_RATES. */ + DBGLOG(P2P, TRACE, ("Ex Support Rate IE\n")); + kalMemCopy(&(prP2pBssInfo->aucAllSupportedRates[prP2pBssInfo->ucAllSupportedRatesLen]), + EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, + EXT_SUP_RATES_IE(pucIE)->ucLength); + + DBGLOG_MEM8(P2P, TRACE, EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, EXT_SUP_RATES_IE(pucIE)->ucLength); + + prP2pBssInfo->ucAllSupportedRatesLen += EXT_SUP_RATES_IE(pucIE)->ucLength; + break; + case ELEM_ID_HT_OP: /* 61 */ /* V */ // TODO: + { +#if 1 + DBGLOG(P2P, TRACE, ("HT OP IE would be overwritten by driver\n")); + + DBGLOG(P2P, TRACE, (" Primary Channel: %x, Info1: %x, Info2: %x, Info3: %x\n", + HT_OP_IE(pucIE)->ucPrimaryChannel, + HT_OP_IE(pucIE)->ucInfo1, + HT_OP_IE(pucIE)->u2Info2, + HT_OP_IE(pucIE)->u2Info3)); +#else + UINT_16 u2Info2 = 0; + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + + DBGLOG(P2P, TRACE, ("HT OP IE\n")); + + /* ucPrimaryChannel. */ + ASSERT(HT_OP_IE(pucIE)->ucPrimaryChannel == prP2pBssInfo->ucPrimaryChannel); + + /* ucInfo1 */ + prP2pBssInfo->ucHtOpInfo1 = HT_OP_IE(pucIE)->ucInfo1; + + /* u2Info2 */ + u2Info2 = HT_OP_IE(pucIE)->u2Info2; + + if (u2Info2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { + ASSERT(prP2pBssInfo->eGfOperationMode != GF_MODE_NORMAL); + u2Info2 &= ~HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (u2Info2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) { + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + u2Info2 &= ~HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + switch (u2Info2 & HT_OP_INFO2_HT_PROTECTION) { + case HT_PROTECT_MODE_NON_HT: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NON_HT; + break; + case HT_PROTECT_MODE_NON_MEMBER: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + break; + default: + prP2pBssInfo->eHtProtectMode = HT_OP_IE(pucIE)->u2Info2; + break; + } + + /* u2Info3 */ + prP2pBssInfo->u2HtOpInfo3 = HT_OP_IE(pucIE)->u2Info3; + + /* aucBasicMcsSet */ + DBGLOG_MEM8(P2P, TRACE, HT_OP_IE(pucIE)->aucBasicMcsSet, 16); +#endif + } + break; + case ELEM_ID_OBSS_SCAN_PARAMS: /* 74 */ /* V */ + { + DBGLOG(P2P, TRACE, ("ELEM_ID_OBSS_SCAN_PARAMS IE would be replaced by driver\n")); + } + break; + case ELEM_ID_EXTENDED_CAP: /* 127 */ /* V */ + { + DBGLOG(P2P, TRACE, ("ELEM_ID_EXTENDED_CAP IE would be replaced by driver\n")); + } + break; + case ELEM_ID_VENDOR: /* 221 */ /* V */ + DBGLOG(P2P, TRACE, ("Vender Specific IE\n")); + { + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && + (u2SubTypeVersion == VERSION_WPA)) { + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP); + ucNewSecMode = TRUE; + } + else if ((ucOuiType == VENDOR_OUI_TYPE_WPS)) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 0, pucIE, IE_SIZE(pucIE)); + } + + // WMM here. + } + else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { + // TODO Store the whole P2P IE & generate later. + // Be aware that there may be one or more P2P IE. + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[prP2pSpecificBssInfo->u2AttributeLen], + pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } + else if(ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[prP2pSpecificBssInfo->u2AttributeLen], + pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } + } + else { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[prP2pSpecificBssInfo->u2AttributeLen], + pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, ("Driver unprocessed Vender Specific IE\n")); + ASSERT(FALSE); + } + + // TODO: Store other Vender IE except for WMM Param. + } + break; + default: + DBGLOG(P2P, TRACE, ("Unprocessed element ID:%d \n", IE_ID(pucIE))); + break; + } + } + + if (!ucNewSecMode && ucOldSecMode) + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_NONE); + + } while (FALSE); + + return; +} /* p2pFuncParseBeaconContent */ + + + + +P_BSS_DESC_T +p2pFuncKeepOnConnection ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo + ) +{ + P_BSS_DESC_T prTargetBss = (P_BSS_DESC_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prConnReqInfo != NULL) && + (prChnlReqInfo != NULL) && + (prScanReqInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + break; + } + + // Update connection request information. + ASSERT(prConnReqInfo->fgIsConnRequest == TRUE); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, + prP2pBssInfo, + prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + } + else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prTargetBss->ucChannelNum; + prChnlReqInfo->eBand = prTargetBss->eBand; + prChnlReqInfo->eChnlSco = prTargetBss->eSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +VOID +p2pFuncStoreAssocRspIEBuffer ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T)NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T)NULL; + INT_16 i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T)prSwRfb->pvHeader; + + if (prAssocRspFrame->u2FrameCtrl != MAC_FRAME_ASSOC_RSP) { + break; + } + + i2IELen = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + + CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN); + + + if (i2IELen <= 0) { + break; + } + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + prJoinInfo->u4BufLength = (UINT_32)i2IELen; + + kalMemCopy(prJoinInfo->aucIEBuf, prAssocRspFrame->aucInfoElem, prJoinInfo->u4BufLength); + + } while (FALSE); + + + return; +} /* p2pFuncStoreAssocRspIEBuffer */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncMgmtFrameRegister ( + IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, + IN BOOLEAN fgIsRegistered, + OUT PUINT_32 pu4P2pPacketFilter + ) +{ + UINT_32 u4NewPacketFilter = 0; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) { + u4NewPacketFilter = *pu4P2pPacketFilter; + } + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, ("Open packet filer probe request\n")); + } + else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, ("Close packet filer probe request\n")); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, ("Open packet filer action frame.\n")); + } + else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, ("Close packet filer action frame.\n")); + } + break; + default: + DBGLOG(P2P, TRACE, ("Ask frog to add code for mgmt:%x\n", u2FrameType)); + break; + } + + if (pu4P2pPacketFilter) { + *pu4P2pPacketFilter = u4NewPacketFilter; + } + +// u4NewPacketFilter |= prAdapter->u4OsPacketFilter; + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, ("P2P Set PACKET filter:0x%lx\n", prAdapter->u4OsPacketFilter)); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8)&prAdapter->u4OsPacketFilter, + &u4NewPacketFilter, + sizeof(u4NewPacketFilter) + ); + + } while (FALSE); + + return; +} /* p2pFuncMgmtFrameRegister */ + + +VOID +p2pFuncUpdateMgmtFrameRegister ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4OsFilter + ) +{ + + do { + + prAdapter->rWifiVar.prP2pFsmInfo->u4P2pPacketFilter = u4OsFilter; + + if ((prAdapter->u4OsPacketFilter & PARAM_PACKET_FILTER_P2P_MASK) ^ u4OsFilter) { + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + + prAdapter->u4OsPacketFilter |= (u4OsFilter & PARAM_PACKET_FILTER_P2P_MASK); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8)&prAdapter->u4OsPacketFilter, + &u4OsFilter, + sizeof(u4OsFilter) + ); + DBGLOG(P2P, TRACE, ("P2P Set PACKET filter:0x%lx\n", prAdapter->u4OsPacketFilter)); + } + + } while (FALSE); + + + + + return; +} /* p2pFuncUpdateMgmtFrameRegister */ + + +VOID +p2pFuncGetStationInfo ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucMacAddr, + OUT P_P2P_STATION_INFO_T prStaInfo + ) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && + (pucMacAddr != NULL) && + (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + // TODO: + + } while (FALSE); + + return; +} /* p2pFuncGetStationInfo */ + + +BOOLEAN +p2pFuncGetAttriList ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + OUT PPUINT_8 ppucAttriList, + OUT PUINT_16 pu2AttriListLen + ) +{ + BOOLEAN fgIsAllocMem = FALSE; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_16 u2Offset = 0; + P_IE_P2P_T prIe = (P_IE_P2P_T)NULL; + PUINT_8 pucAttriListStart = (PUINT_8)NULL; + UINT_16 u2AttriListLen = 0, u2BufferSize = 0; + BOOLEAN fgBackupAttributes = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (pucIE != NULL) && + (u2IELength != 0) && + (ppucAttriList != NULL) && + (pu2AttriListLen != NULL)); + + if(ppucAttriList) { + *ppucAttriList = NULL; + } + if(pu2AttriListLen) { + *pu2AttriListLen = 0; + } + + if (ucOuiType == VENDOR_OUI_TYPE_WPS){ + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + } + else if ((ucOuiType != VENDOR_OUI_TYPE_P2P) +#if CFG_SUPPORT_WFD + && (ucOuiType != VENDOR_OUI_TYPE_WFD) +#endif + ) { + DBGLOG(P2P, INFO, ("Not supported OUI Type to parsing 0x%x\n", ucOuiType)); + break; + } + + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_VENDOR == IE_ID(pucIE)) { + prIe = (P_IE_P2P_T)pucIE; + + if (prIe->ucLength <= P2P_OUI_TYPE_LEN) { + continue; + + } + + if ((prIe->aucOui[0] == aucWfaOui[0]) && + (prIe->aucOui[1] == aucWfaOui[1]) && + (prIe->aucOui[2] == aucWfaOui[2]) && + (ucOuiType == prIe->ucOuiType)) { + + if (!pucAttriListStart) { + pucAttriListStart = &prIe->aucP2PAttributes[0]; + if (prIe->ucLength > P2P_OUI_TYPE_LEN) { + u2AttriListLen = (UINT_16)(prIe->ucLength - P2P_OUI_TYPE_LEN); + } + else { + ASSERT(FALSE); + } + } + else { +/* More than 2 attributes. */ + UINT_16 u2CopyLen; + + if (FALSE == fgBackupAttributes) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo;; + + fgBackupAttributes = TRUE; + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[0], + pucAttriListStart, + u2AttriListLen); + + pucAttriListStart = &prP2pSpecificBssInfo->aucAttributesCache[0]; + + u2BufferSize = P2P_MAXIMUM_ATTRIBUTE_LEN; + } + else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalMemCopy(&prP2pSpecificBssInfo->aucWscAttributesCache[0], + pucAttriListStart, + u2AttriListLen); + pucAttriListStart = &prP2pSpecificBssInfo->aucWscAttributesCache[0]; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + PUINT_8 pucTmpBuf = (PUINT_8)NULL; + pucTmpBuf = (PUINT_8)kalMemAlloc(WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, VIR_MEM_TYPE); + + if (pucTmpBuf != NULL) { + fgIsAllocMem = TRUE; + } + else { + /* Can't alloca memory for WFD IE relocate. */ + ASSERT(FALSE); + break; + } + + kalMemCopy(pucTmpBuf, + pucAttriListStart, + u2AttriListLen); + + pucAttriListStart = pucTmpBuf; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#endif + else { + fgBackupAttributes = FALSE; + } + } + + u2CopyLen = (UINT_16)(prIe->ucLength - P2P_OUI_TYPE_LEN); + + if ((u2AttriListLen + u2CopyLen) > u2BufferSize) { + + u2CopyLen = u2BufferSize - u2AttriListLen; + + DBGLOG(P2P, WARN, ("Length of received P2P attributes > maximum cache size.\n")); + + } + + if (u2CopyLen) { + kalMemCopy((PUINT_8)((UINT_32)pucAttriListStart + (UINT_32)u2AttriListLen), + &prIe->aucP2PAttributes[0], + u2CopyLen); + + u2AttriListLen += u2CopyLen; + } + + + } + } /* prIe->aucOui */ + } /* ELEM_ID_VENDOR */ + } /* IE_FOR_EACH */ + + + } while (FALSE); + + if (pucAttriListStart) { + PUINT_8 pucAttribute = pucAttriListStart; + DBGLOG(P2P, LOUD, ("Checking Attribute Length.\n")); + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset); + } + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + } + else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, ("Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), + WSC_ATTRI_LEN(pucAttribute))); + } + } + else { + } + + ASSERT(u2Offset == u2AttriListLen); + + *ppucAttriList = pucAttriListStart; + *pu2AttriListLen = u2AttriListLen; + + } + else { + *ppucAttriList = (PUINT_8)NULL; + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + + +P_MSDU_INFO_T +p2pFuncProcessP2pProbeRsp ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMgmtTxMsdu + ) +{ + P_MSDU_INFO_T prRetMsduInfo = prMgmtTxMsdu; + P_WLAN_PROBE_RSP_FRAME_T prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T)NULL; + PUINT_8 pucIEBuf = (PUINT_8)NULL; + UINT_16 u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; + BOOLEAN fgIsP2PIE = FALSE, fgIsWSCIE = FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + UINT_32 u4IeArraySize = 0, u4Idx = 0; + + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + //3 Make sure this is probe response frame. + prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T)((UINT_32)prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP); + + //3 Get the importent P2P IE. + u2ProbeRspHdrLen = (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + pucIEBuf = prProbeRspFrame->aucInfoElem; + u2IELength = prMgmtTxMsdu->u2FrameLength - u2ProbeRspHdrLen; + +#if CFG_SUPPORT_WFD + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen = 0; +#endif + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, + SSID_IE(pucIEBuf)->ucLength); + } + break; + case ELEM_ID_VENDOR: + { + UINT_8 ucOuiType = 0; + UINT_16 u2SubTypeVersion = 0; +#if! CFG_SUPPORT_WFD + + + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 2, pucIEBuf, IE_SIZE(pucIEBuf)); + fgIsWSCIE = TRUE; + } + + } + + else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + //2 Note(frog): I use WSC IE buffer for Probe Request to store the P2P IE for Probe Response. + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 1, pucIEBuf, IE_SIZE(pucIEBuf)); + fgIsP2PIE = TRUE; + } + + } + + + + else { + if((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen+IE_SIZE(pucIEBuf))<512) { + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += IE_SIZE(pucIEBuf); + } + } +#else + /* Eddie May be WFD */ + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if(ucOuiType == VENDOR_OUI_TYPE_WMM) { + break; + } + + } + if((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen+IE_SIZE(pucIEBuf))<1024) { + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen + , pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += IE_SIZE(pucIEBuf); + } +#endif + + + } + break; + default: + break; + } + + } + + + //3 Check the total size & current frame. + u2EstimateSize = WLAN_MAC_MGMT_HEADER_LEN + \ + TIMESTAMP_FIELD_LEN + \ + BEACON_INTERVAL_FIELD_LEN + \ + CAP_INFO_FIELD_LEN + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + \ + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET); + + u2EstimatedExtraIELen = 0; + + u4IeArraySize = sizeof(txProbeRspIETable)/sizeof(APPEND_VAR_IE_ENTRY_T); + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += txProbeRspIETable[u4Idx].u2EstimatedFixedIELen; + } + + else { + ASSERT(txProbeRspIETable[u4Idx].pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += (UINT_16)(txProbeRspIETable[u4Idx].pfnCalculateVariableIELen(prAdapter, + NETWORK_TYPE_P2P_INDEX, + NULL)); + } + + } + + + if (fgIsWSCIE) { + u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); + } + + if (fgIsP2PIE) { + u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); + } + +#if CFG_SUPPORT_WFD + u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; +#endif + + + + if ((u2EstimateSize += u2EstimatedExtraIELen) > (prRetMsduInfo->u2FrameLength)) { + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimateSize); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, ("No packet for sending new probe response, use original one\n")); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + + prRetMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } + + + //3 Compose / Re-compose probe response frame. + bssComposeBeaconProbeRespFrameHeaderAndFF( + (PUINT_8)((UINT_32)(prRetMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prProbeRspFrame->aucDestAddr, + prProbeRspFrame->aucSrcAddr, + prProbeRspFrame->aucBSSID, + prProbeRspFrame->u2BeaconInterval, + prProbeRspFrame->u2CapInfo); + + prRetMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + + bssBuildBeaconProbeRespFrameCommonIEs(prRetMsduInfo, + prP2pBssInfo, + prProbeRspFrame->aucDestAddr); + + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) { + txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prRetMsduInfo); + } + + } + + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (PUINT_8)((UINT_32)prRetMsduInfo->prPacket + (UINT_32)prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); + } + + if (fgIsP2PIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 1, + (PUINT_8)((UINT_32)prRetMsduInfo->prPacket + (UINT_32)prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); + } + +#if CFG_SUPPORT_WFD + if(prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen>0) { + kalMemCopy((PUINT_8)((UINT_32)prRetMsduInfo->prPacket + (UINT_32)prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen); + prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; + } +#endif + + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) { + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + } + + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + + +#if 0 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + break; + } + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID +p2pFuncGenerateExtra_IEForBeacon ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + PUINT_8 pucIEBuf = (PUINT_8)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + + break; + } + + pucIEBuf = (PUINT_8)((UINT_32)prMsduInfo->prPacket + (UINT_32)prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucBeaconIECache, prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + + return; +} /* p2pFuncGenerateExtra_IEForBeacon */ + + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (!prAdapter->fgIsP2PRegistered) { + break; + } + + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + break; + } + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + + +VOID +p2pFuncGenerateP2p_IEForBeacon ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + PUINT_8 pucIEBuf = (PUINT_8)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) { + break; + } + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + + break; + } + + pucIEBuf = (PUINT_8)((UINT_32)prMsduInfo->prPacket + (UINT_32)prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return; +} /* p2pFuncGenerateP2p_IEForBeacon */ + + + + + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) { + return 0; + } + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + + +VOID +p2pFuncGenerateWSC_IEForBeacon ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) { + return; + } + + u2IELen = (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + // TODO: Check P2P FSM State. + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 0, + pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + + return; +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) { + return 0; + } + + return p2pFuncCalculateP2P_IELen(prAdapter, + eNetTypeIndex, + prStaRec, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable)/sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncGenerateP2p_IEForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (IS_STA_P2P_TYPE(prStaRec)) { + DBGLOG(P2P, TRACE, ("Generate NULL P2P IE for Assoc Rsp.\n")); + + p2pFuncGenerateP2P_IE(prAdapter, + TRUE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable)/sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + } + else { + + DBGLOG(P2P, TRACE, ("Legacy device, no P2P IE.\n")); + } + + } while (FALSE); + + return; + +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + DBGLOG(P2P, TRACE, ("p2pFuncCalculateWSC_IELenForAssocRsp\n")); + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) { + return 0; + } + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + + +VOID +p2pFuncGenerateWSC_IEForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) { + return; + } + DBGLOG(P2P, TRACE, ("p2pFuncGenerateWSC_IEForAssocRsp\n")); + + u2IELen = (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + // TODO: Check P2P FSM State. + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 0, + pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + + return; +} +/* p2pFuncGenerateP2p_IEForAssocRsp */ + + + + +UINT_32 +p2pFuncCalculateP2P_IELen ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ) +{ + + UINT_32 u4OverallAttriLen, u4Dummy; + UINT_16 u2EstimatedFixedAttriLen; + UINT_32 i; + + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + u2EstimatedFixedAttriLen = arAppendAttriTable[i].u2EstimatedFixedAttriLen; + + if (u2EstimatedFixedAttriLen) { + u4OverallAttriLen += u2EstimatedFixedAttriLen; + } + else { + ASSERT(arAppendAttriTable[i].pfnCalculateVariableAttriLen); + + u4OverallAttriLen += + arAppendAttriTable[i].pfnCalculateVariableAttriLen(prAdapter, prStaRec); + } + } + + u4Dummy = u4OverallAttriLen; + u4OverallAttriLen += P2P_IE_OUI_HDR; + + for (;(u4Dummy > P2P_MAXIMUM_ATTRIBUTE_LEN);) { + u4OverallAttriLen += P2P_IE_OUI_HDR; + u4Dummy -= P2P_MAXIMUM_ATTRIBUTE_LEN; + } + + return u4OverallAttriLen; +} /* p2pFuncCalculateP2P_IELen */ + + +VOID +p2pFuncGenerateP2P_IE ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ) +{ + PUINT_8 pucBuffer = (PUINT_8)NULL; + P_IE_P2P_T prIeP2P = (P_IE_P2P_T)NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (P_IE_P2P_T)pucBuffer; + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + (*pu2Offset) += P2P_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeP2P->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = (PUINT_8)((UINT_32)prIeP2P + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (P_IE_P2P_T)((UINT_32)prIeP2P + + (ELEM_HDR_LEN + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN))); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + kalMemCopy(prIeP2P->aucP2PAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += P2P_IE_OUI_HDR; + } + + } + + } + + prIeP2P->ucLength = (UINT_8)(VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + + } while (FALSE); + + return; +} /* p2pFuncGenerateP2P_IE */ + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + PUINT_8 pucBuffer; + P_P2P_ATTRI_STATUS_T prAttriStatus; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + UINT_32 u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (fgIsAssocFrame) { + return u4AttriLen; + } + + // TODO: For assoc request P2P IE check in driver & return status in P2P IE. + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + + (UINT_32)(*pu2Offset)); + + ASSERT(pucBuffer); + prAttriStatus = (P_P2P_ATTRI_STATUS_T)pucBuffer; + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16)u4AttriLen)); + + + + + prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; + WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); + + prAttriStatus->ucStatusCode = P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriStatusForAssocRsp */ + +UINT_32 +p2pFuncAppendAttriExtListenTiming ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + P_P2P_ATTRI_EXT_LISTEN_TIMING_T prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + PUINT_8 pucBuffer = NULL; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) { + return u4AttriLen; + } + + // TODO: For extend listen timing. + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16)u4AttriLen)); + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + + (UINT_32)(*pu2Offset)); + + ASSERT(pucBuffer); + + prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T)pucBuffer; + + prP2pExtListenTiming->ucId = P2P_ATTRI_ID_EXT_LISTEN_TIMING; + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2Length, P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailInterval, prP2pSpecificBssInfo->u2AvailabilityInterval); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailPeriod, prP2pSpecificBssInfo->u2AvailabilityPeriod); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriExtListenTiming */ + + +P_IE_HDR_T +p2pFuncGetSpecIE ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2BufferLen, + IN UINT_8 ucElemID, + IN PBOOLEAN pfgIsMore + ) +{ + P_IE_HDR_T prTargetIE = (P_IE_HDR_T)NULL; + PUINT_8 pucIE = (PUINT_8)NULL; + UINT_16 u2Offset = 0; + + if (pfgIsMore) { + *pfgIsMore = FALSE; + } + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + else { + prTargetIE = (P_IE_HDR_T)pucIE; + + if (pfgIsMore == NULL) { + break; + } + + } + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + + + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIEBuf, + IN UINT_16 u2BufferLen, + IN UINT_16 u2AttriID + ) +{ + P_IE_P2P_T prP2pIE = (P_IE_P2P_T)NULL; + P_ATTRIBUTE_HDR_T prTargetAttri = (P_ATTRIBUTE_HDR_T)NULL; + BOOLEAN fgIsMore = FALSE; + PUINT_8 pucIE = (PUINT_8)NULL, pucAttri = (PUINT_8)NULL; + UINT_16 u2OffsetAttri = 0; + UINT_16 u2BufferLenLeft = 0; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + + DBGLOG(P2P, INFO, ("Check AssocReq Oui type %u attri %u for len %u\n",ucOuiType, u2AttriID, u2BufferLen)); + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + u2BufferLenLeft = u2BufferLen; + pucIE = pucIEBuf; + do { + fgIsMore = FALSE; + prP2pIE = (P_IE_P2P_T)p2pFuncGetSpecIE(prAdapter, + pucIE, + u2BufferLenLeft, + ELEM_ID_VENDOR, + &fgIsMore); + + if (prP2pIE) { + + ASSERT(prP2pIE>pucIE); + + u2BufferLenLeft = u2BufferLen - (UINT_16)( ((UINT_32)prP2pIE) - ((UINT_32)pucIEBuf)); + + DBGLOG(P2P, INFO, ("Find vendor id %u len %u oui %u more %u LeftLen %u\n", + IE_ID(prP2pIE), IE_LEN(prP2pIE), prP2pIE->ucOuiType, fgIsMore, u2BufferLenLeft)); + + if(IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) { + + if (prP2pIE->ucOuiType == ucOuiType) { + switch (ucOuiType) { + case VENDOR_OUI_TYPE_WPS: + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + break; + case VENDOR_OUI_TYPE_P2P: + break; + case VENDOR_OUI_TYPE_WPA: + case VENDOR_OUI_TYPE_WMM: + case VENDOR_OUI_TYPE_WFD: + default: + break; + } + + + if ((prP2pIE->aucOui[0] == aucWfaOui[0]) + && (prP2pIE->aucOui[1] == aucWfaOui[1]) + && (prP2pIE->aucOui[2] == aucWfaOui[2]) + ) { + + u2OffsetAttri = 0; + pucAttri = prP2pIE->aucP2PAttributes; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + WSC_ATTRI_FOR_EACH(pucAttri, (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + //LOG_FUNC("WSC: attri id=%u len=%u\n",WSC_ATTRI_ID(pucAttri), WSC_ATTRI_LEN(pucAttri)); + if (WSC_ATTRI_ID(pucAttri) == u2AttriID) { + prTargetAttri = (P_ATTRIBUTE_HDR_T)pucAttri; + break; + } + + } + + } + + else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + //LOG_FUNC("P2P: attri id=%u len=%u\n",ATTRI_ID(pucAttri), ATTRI_LEN(pucAttri)); + if (ATTRI_ID(pucAttri) == (UINT_8)u2AttriID) { + prTargetAttri = (P_ATTRIBUTE_HDR_T)pucAttri; + break; + } + + } + + } + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + //DBGLOG(P2P, INFO, ("WFD: attri id=%u len=%u\n",WFD_ATTRI_ID(pucAttri), WFD_ATTRI_LEN(pucAttri))); + if (ATTRI_ID(pucAttri) == (UINT_8)u2AttriID) { + prTargetAttri = (P_ATTRIBUTE_HDR_T)pucAttri; + break; + } + + } + } + else { + // Possible or else. + } + + } + } /* ucOuiType */ + } /* P2P_OUI_TYPE_LEN */ + + pucIE = (PUINT_8)(((UINT_32)prP2pIE) + IE_SIZE(prP2pIE)); + + } /* prP2pIE */ + + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + } while (FALSE); + + return prTargetAttri; +} +/* p2pFuncGetSpecAttri */ + + +WLAN_STATUS +p2pFuncGenerateBeaconProbeRsp ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_MSDU_INFO_T prMsduInfo, + IN BOOLEAN fgIsProbeRsp + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T)NULL; +// P_APPEND_VAR_IE_ENTRY_T prAppendIeTable = (P_APPEND_VAR_IE_ENTRY_T)NULL; + + + do { + + ASSERT_BREAK((prAdapter != NULL) && + (prBssInfo != NULL) && + (prMsduInfo != NULL)); + + +// txBcnIETable + +// txProbeRspIETable + + + + prBcnFrame = (P_WLAN_BEACON_FRAME_T)prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBssInfo->u2CapInfo, + (PUINT_8)prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncGenerateBeaconProbeRsp */ + + +WLAN_STATUS +p2pFuncComposeBeaconProbeRspTemplate ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBcnBuffer, + IN UINT_32 u4BcnBufLen, + IN BOOLEAN fgIsProbeRsp, + IN P_P2P_PROBE_RSP_UPDATE_INFO_T prP2pProbeRspInfo, + IN BOOLEAN fgSynToFW + ) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T)NULL; + P_WLAN_MAC_HEADER_T prWlanBcnFrame = (P_WLAN_MAC_HEADER_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + PUINT_8 pucBuffer = (PUINT_8)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBcnBuffer != NULL)); + + prWlanBcnFrame = (P_WLAN_MAC_HEADER_T)pucBcnBuffer; + + if ((prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_BEACON) && (!fgIsProbeRsp)) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + else if (prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_PROBE_RSP) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + + + if (fgIsProbeRsp) { + ASSERT_BREAK(prP2pProbeRspInfo != NULL); + + if (!prP2pProbeRspInfo->prProbeRspMsduTemplate) { + cnmMgtPktFree(prAdapter, prP2pProbeRspInfo->prProbeRspMsduTemplate); + } + + prP2pProbeRspInfo->prProbeRspMsduTemplate = cnmMgtPktAlloc(prAdapter, u4BcnBufLen); + + prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + } + else { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > (OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + + pucBuffer = (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (UINT_16)u4BcnBufLen; + + if (fgSynToFW) { + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + } + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + + + + + + + + + + + + + + + + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c new file mode 100755 index 000000000000..33cafca9ca04 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c @@ -0,0 +1,582 @@ +#include "p2p_precomp.h" + +#if CFG_SUPPORT_WFD +#if CFG_SUPPORT_WFD_COMPOSE_IE +#if 0 +APPEND_VAR_ATTRI_ENTRY_T txProbeRspWFDAttributesTable[] = { + { (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO) , NULL, wfdFuncAppendAttriDevInfo } /* 0 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid } /* 1 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo } /* 6 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_EXT_CAPABILITY), NULL, wfdFuncAppendAttriExtCapability } /* 7 */ + ,{ 0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo } /* 9 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txBeaconWFDAttributesTable[] = { + { (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO) , NULL, wfdFuncAppendAttriDevInfo } /* 0 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid } /* 1 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo } /* 6 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txAssocReqWFDAttributesTable[] = { + { (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO) , NULL, wfdFuncAppendAttriDevInfo } /* 0 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid } /* 1 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo } /* 6 */ +}; +#endif + +APPEND_VAR_ATTRI_ENTRY_T txAssocRspWFDAttributesTable[] = { + { (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO) , NULL, wfdFuncAppendAttriDevInfo } /* 0 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid } /* 1 */ + ,{ (WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo } /* 6 */ + ,{ 0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo } /* 9 */ + +}; + +#endif + + + + +UINT_32 +p2pCalculate_IEForAssocReq ( + + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T)NULL; + UINT_32 u4RetValue = 0; + + do { + ASSERT_BREAK((eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) && (prAdapter != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + // ADD HT Capability + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + + // ADD WMM Information Element + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + } while (FALSE); + + return u4RetValue; +} /* p2pCalculate_IEForAssocReq */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pGenerate_IEForAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T)NULL; + PUINT_8 pucIEBuf = (PUINT_8)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + pucIEBuf = (PUINT_8)((UINT_32)prMsduInfo->prPacket + (UINT_32)prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + rlmReqGenerateHtCapIE (prAdapter,prMsduInfo); + mqmGenerateWmmInfoIE (prAdapter,prMsduInfo); + + + } while (FALSE); + + return; + +} /* p2pGenerate_IEForAssocReq */ + + + +UINT_32 +wfdFuncAppendAttriDevInfo ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_DEVICE_INFORMATION_IE_T prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T)NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (UINT_32)(*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T)pucBuffer; + + prWfdDevInfo->ucElemID = WFD_ATTRI_ID_DEV_INFO; + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevInfo, prWfdCfgSettings->u2WfdDevInfo); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2SessionMgmtCtrlPort, prWfdCfgSettings->u2WfdControlPort); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevMaxSpeed, prWfdCfgSettings->u2WfdMaximumTp); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2Length, WFD_ATTRI_MAX_LEN_DEV_INFO); + + u4AttriLen = WFD_ATTRI_MAX_LEN_DEV_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} +/* wfdFuncAppendAttriDevInfo */ + +UINT_32 +wfdFuncAppendAttriAssocBssid ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_ASSOCIATED_BSSID_IE_T prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T)NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + P_BSS_INFO_T prAisBssInfo = (P_BSS_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if (prWfdCfgSettings->ucWfdEnable == 0) { + break; + } + + /* AIS network. */ + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if ((!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) || + (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED)) { + break; + } + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (UINT_32)(*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T)pucBuffer; + + prWfdAssocBssid->ucElemID = WFD_ATTRI_ID_ASSOC_BSSID; + + WLAN_SET_FIELD_BE16(&prWfdAssocBssid->u2Length, WFD_ATTRI_MAX_LEN_ASSOC_BSSID); + + COPY_MAC_ADDR(prWfdAssocBssid->aucAssocBssid, prAisBssInfo->aucBSSID); + + u4AttriLen = WFD_ATTRI_MAX_LEN_ASSOC_BSSID + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} +/* wfdFuncAppendAttriAssocBssid */ + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_COUPLE_SINK_INFORMATION_IE_T prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T)NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_SINK_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (UINT_32)(*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T)pucBuffer; + + prWfdCoupleSinkInfo->ucElemID = WFD_ATTRI_ID_COUPLED_SINK_INFO; + + WLAN_SET_FIELD_BE16(&prWfdCoupleSinkInfo->u2Length, WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO); + + COPY_MAC_ADDR(prWfdCoupleSinkInfo->aucCoupleSinkMac, prWfdCfgSettings->aucWfdCoupleSinkAddress); + + prWfdCoupleSinkInfo->ucCoupleSinkStatusBp = prWfdCfgSettings->ucWfdCoupleSinkStatus; + + u4AttriLen = WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} +/* wfdFuncAppendAttriCoupledSinkInfo */ + +UINT_32 +wfdFuncAppendAttriExtCapability ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_EXTENDED_CAPABILITY_IE_T prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T)NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_EXT_CAPABILITY_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (UINT_32)(*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T)pucBuffer; + + prWfdExtCapability->ucElemID = WFD_ATTRI_ID_EXT_CAPABILITY; + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2Length, WFD_ATTRI_MAX_LEN_EXT_CAPABILITY); + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2WfdExtCapabilityBp, prWfdCfgSettings->u2WfdExtendCap); + + u4AttriLen = WFD_ATTRI_MAX_LEN_EXT_CAPABILITY + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} +/* wfdFuncAppendAttriExtCapability */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate length of Channel List Attribute +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of Attribute added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +wfdFuncCalculateAttriLenSessionInfo ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + UINT_16 u2AttriLen = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + if (prWfdCfgSettings->ucWfdEnable == 0) { + break; + } + + u2AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + + return (UINT_32)u2AttriLen; + +} /* wfdFuncCalculateAttriLenSessionInfo */ + + +UINT_32 +wfdFuncAppendAttriSessionInfo ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize + ) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_SESSION_INFORMATION_IE_T prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T)NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || (prWfdCfgSettings->u2WfdSessionInformationIELen == 0)) { + break; + } + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (UINT_32)(*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T)pucBuffer; + + prWfdSessionInfo->ucElemID = WFD_ATTRI_ID_SESSION_INFO; + + // TODO: Check endian issue? + kalMemCopy(prWfdSessionInfo->pucWfdDevInfoDesc, prWfdCfgSettings->aucWfdSessionInformationIE, prWfdCfgSettings->u2WfdSessionInformationIELen); + + WLAN_SET_FIELD_16(&prWfdSessionInfo->u2Length, prWfdCfgSettings->u2WfdSessionInformationIELen); + + u4AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } +while (FALSE); + + (*pu2Offset) += (UINT_16)u4AttriLen; + + return u4AttriLen; +} +/* wfdFuncAppendAttriSessionInfo */ + + + +#if CFG_SUPPORT_WFD_COMPOSE_IE +VOID +wfdFuncGenerateWfd_IE ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize + ) +{ + + + PUINT_8 pucBuffer = (PUINT_8)NULL; + P_IE_WFD_T prIeWFD = (P_IE_WFD_T)NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8)((UINT_32)pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= WFD_IE_OUI_HDR); + + prIeWFD = (P_IE_WFD_T)pucBuffer; + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + (*pu2Offset) += WFD_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeWFD->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = (PUINT_8)((UINT_32)prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeWFD = (P_IE_WFD_T)((UINT_32)prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + kalMemCopy(prIeWFD->aucWFDAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += WFD_IE_OUI_HDR; + } + + } + + } + + prIeWFD->ucLength = (UINT_8)(VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + + } while (FALSE); + + return; +} /* wfdFuncGenerateWfd_IE */ + +#endif /* CFG_SUPPORT_WFD_COMPOSE_IE */ + + + + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec + ) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + if ( + !IS_STA_P2P_TYPE(prStaRec) || + (prWfdCfgSettings->ucWfdEnable == 0)) { + return 0; + } + + return p2pFuncCalculateP2P_IELen(prAdapter, + eNetTypeIndex, + prStaRec, + txAssocRspWFDAttributesTable, + sizeof(txAssocRspWFDAttributesTable)/sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + +#else + return 0; +#endif +} /* wfdFuncCalculateWfdIELenForAssocRsp */ + + + +VOID +wfdFuncGenerateWfdIEForAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + P_STA_RECORD_T prStaRec; + + do { + ASSERT_BREAK((prMsduInfo != NULL) && (prAdapter != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (IS_STA_P2P_TYPE(prStaRec)) { + + if (prWfdCfgSettings->ucWfdEnable == 0) { + break; + } + if((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0) { + break; + } + + wfdFuncGenerateWfd_IE(prAdapter, + FALSE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspWFDAttributesTable, + sizeof(txAssocRspWFDAttributesTable)/sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + } + } while (FALSE); + + return; +#else + + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c new file mode 100755 index 000000000000..a01e1cab20e5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c @@ -0,0 +1,1018 @@ +/* +** $Id: @(#) p2p_rlm.c@@ +*/ + +/*! \file "p2p_rlm.c" + \brief + +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +extern VOID +rlmSyncOperationParams ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init AP Bss +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmBssInitForAP( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + ENUM_BAND_T eBand; + UINT_8 ucChannel; + ENUM_CHNL_EXT_T eSCO; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + return; + } + + /* Operation band, channel shall be ready before invoking this function. + * Bandwidth may be ready if other network is connected + */ + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + + if (RLM_AP_IS_BW_40_ALLOWED(prAdapter, prBssInfo)) { + /* In this case, the first BSS's SCO is 40MHz and known, so AP can + * apply 40MHz bandwidth, but the first BSS's SCO may be changed + * later if its Beacon lost timeout occurs + */ + if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) && + eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && + eBand == prBssInfo->eBand) { + prBssInfo->eBssSCO = eSCO; + } + else if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex)) { + prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo); + } + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + prBssInfo->fg40mBwAllowed = TRUE; + prBssInfo->fgAssoc40mBwAllowed = TRUE; + + prBssInfo->ucHtOpInfo1 = (UINT_8) + (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); + + rlmUpdateBwByChListForAP(prAdapter, prBssInfo); + } + } + + DBGLOG(RLM, INFO, ("WLAN AP SCO=%d\n", prBssInfo->eBssSCO)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmRspGenerateObssScanIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_IE_OBSS_SCAN_PARAM_T prObssScanIe; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11N(prBssInfo) && !RLM_NET_IS_BOW(prBssInfo) && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) && + prBssInfo->eBand == BAND_2G4 && + prBssInfo->eBssSCO != CHNL_EXT_SCN) { + + prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add 20/40 BSS coexistence IE */ + prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; + prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN; + + prObssScanIe->u2ScanPassiveDwell = + dot11OBSSScanPassiveDwell; + prObssScanIe->u2ScanActiveDwell = + dot11OBSSScanActiveDwell; + prObssScanIe->u2TriggerScanInterval = + dot11BSSWidthTriggerScanInterval; + prObssScanIe->u2ScanPassiveTotalPerChnl = + dot11OBSSScanPassiveTotalPerChannel; + prObssScanIe->u2ScanActiveTotalPerChnl = + dot11OBSSScanActiveTotalPerChannel; + prObssScanIe->u2WidthTransDelayFactor = + dot11BSSWidthChannelTransitionDelayFactor; + prObssScanIe->u2ScanActivityThres = + dot11OBSSScanActivityThreshold; + + ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN+ ELEM_MAX_LEN_OBSS_SCAN)); + + prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P GO. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmUpdateBwByChListForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + UINT_8 ucLevel; + BOOLEAN fgBwChange; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + fgBwChange = FALSE; + + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) { + return fgBwChange; + } + + ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand, + prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO); + + if (ucLevel == CHNL_LEVEL0) { + /* Forced to 20MHz, so extended channel is SCN and STA width is zero */ + prBssInfo->fgObssActionForcedTo20M = TRUE; + + if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + fgBwChange = TRUE; + } + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + OBSS_20_40M_TIMEOUT * MSEC_PER_SEC); + } + + /* Clear up all channel lists */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + return fgBwChange; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmProcessPublicAction ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ) +{ + P_ACTION_20_40_COEXIST_FRAME prRxFrame; + P_IE_20_40_COEXIST_T prCoexist; + P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + PUINT_8 pucIE; + UINT_16 u2IELength, u2Offset; + UINT_8 i, j; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || + HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != + NETWORK_TYPE_P2P_INDEX) { + return; + } + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT || + prBssInfo->eBssSCO == CHNL_EXT_SCN) { + return; + } + + prCoexist = &prRxFrame->rBssCoexist; + if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT|BSS_COEXIST_20M_REQ)) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == + prBssInfo->ucPrimaryChannel) { + break; + } + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && + (i <= CHNL_LIST_SZ_2G)){ + prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + + /* Process intolerant channel report IE */ + pucIE = (PUINT_8) &prRxFrame->rChnlReport; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT: + prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE; + + if (prChnlReport->ucLength <= 1) { + break; + } + + /* To do: process regulatory class. Now we assume 2.4G band */ + + for (j = 0; j < prChnlReport->ucLength - 1; j++) { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == + prChnlReport->aucChannelList[j]) { + break; + } + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && + (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = + prChnlReport->aucChannelList[j]; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + } + break; + + default: + break; + } + } /* end of IE_FOR_EACH */ + + if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) { + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); + rlmSyncOperationParams(prAdapter, prBssInfo); + } + + /* Check if OBSS scan exemption response should be sent */ + if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ) { + rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmProcessHtAction ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ) +{ + P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) { + return; + } + + /* To do: depending regulation class 13 and 14 based on spec + * Note: (ucChannelWidth==1) shall restored back to original capability, + * not current setting to 40MHz BW here + */ + if (prRxFrame->ucChannelWidth == 0) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + } + else if (prRxFrame->ucChannelWidth == 1) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmHandleObssStatusEventPkt ( + P_ADAPTER_T prAdapter, + P_EVENT_AP_OBSS_STATUS_T prObssStatus + ) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prObssStatus->ucNetTypeIndex]; + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + + prBssInfo->fgObssErpProtectMode = + (BOOLEAN) prObssStatus->ucObssErpProtectMode; + prBssInfo->eObssHtProtectMode = + (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode; + prBssInfo->eObssGfOperationMode = + (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode; + prBssInfo->fgObssRifsOperationMode = + (BOOLEAN) prObssStatus->ucObssRifsOperationMode; + prBssInfo->fgObssBeaconForcedTo20M = + (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmUpdateParamsForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + BOOLEAN fgUpdateBeacon + ) +{ + P_LINK_T prStaList; + P_STA_RECORD_T prStaRec; + BOOLEAN fgErpProtectMode, fgSta40mIntolerant; + BOOLEAN fgUseShortPreamble, fgUseShortSlotTime; + ENUM_HT_PROTECT_MODE_T eHtProtectMode; + ENUM_GF_MODE_T eGfOperationMode; + UINT_8 ucHtOpInfo1; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + return; + } + + fgErpProtectMode = FALSE; + eHtProtectMode = HT_PROTECT_MODE_NONE; + eGfOperationMode = GF_MODE_NORMAL; + fgSta40mIntolerant = FALSE; + fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + fgUseShortSlotTime = TRUE; + ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + + prStaList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) { + //ASSERT(prStaRec); + if(!prStaRec){ + DBGLOG(P2P, TRACE, ("prStaRec is NULL in rlmUpdateParamsForAP() \n")); + break; + } + if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 && + prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) { + if (!(prStaRec->ucPhyTypeSet & + (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) { + /* B-only mode, so mode 1 (ERP protection) */ + fgErpProtectMode = TRUE; + } + + if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* BG-only or A-only */ + eHtProtectMode = HT_PROTECT_MODE_NON_HT; + } + else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) { + /* 20MHz-only */ + if (eHtProtectMode == HT_PROTECT_MODE_NONE) { + eHtProtectMode = HT_PROTECT_MODE_20M; + } + } + + if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF)) { + eGfOperationMode = GF_MODE_PROTECT; + } + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) { + fgUseShortPreamble = FALSE; + } + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) { + fgUseShortSlotTime = FALSE; + } + + if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) { + fgSta40mIntolerant = TRUE; + } + } + } /* end of LINK_FOR_EACH_ENTRY */ + + /* Check if HT operation IE about 20/40M bandwidth shall be updated */ + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant && + !prBssInfo->fgObssActionForcedTo20M && + !prBssInfo->fgObssBeaconForcedTo20M) { + + ucHtOpInfo1 = (UINT_8) + (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); + } + } + + /* Check if any new parameter may be updated */ + if (prBssInfo->fgErpProtectMode != fgErpProtectMode || + prBssInfo->eHtProtectMode != eHtProtectMode || + prBssInfo->eGfOperationMode != eGfOperationMode || + prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 || + prBssInfo->fgUseShortPreamble != fgUseShortPreamble || + prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) { + + prBssInfo->fgErpProtectMode = fgErpProtectMode; + prBssInfo->eHtProtectMode = eHtProtectMode; + prBssInfo->eGfOperationMode = eGfOperationMode; + prBssInfo->ucHtOpInfo1 = ucHtOpInfo1; + prBssInfo->fgUseShortPreamble = fgUseShortPreamble; + prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime; + + if (fgUseShortSlotTime) { + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + else { + prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + } + + rlmSyncOperationParams(prAdapter, prBssInfo); + fgUpdateBeacon = TRUE; + } + + /* Update Beacon content if related IE content is changed */ + if (fgUpdateBeacon) { + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initial the channel list from the domain information. +* This function is called after P2P initial and Domain information changed. +* Make sure the device is disconnected while changing domain information. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFuncInitialChannelList ( + IN P_ADAPTER_T prAdapter + ) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY)NULL; + P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO)NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)NULL; + UINT_32 u4Idx = 0, u4IdxII = 0; + UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0; +#endif + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; +#if 0 + ucAutoChnl = prP2pConnSetting->ucOperatingChnl; +#endif + + prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter); + + ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL)); + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField; + + for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) { + prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx]; + + + if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) || + (prDomainSubBand->ucBand == BAND_NULL)) { + continue; + } + + + if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) { + /* Buffer is not enough to include all supported channels. */ + break; // for + } + + prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass; + prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels; + + for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) { + prChannelEntryField->aucChannelList[u4IdxII] = prDomainSubBand->ucFirstChannelNum + + (u4IdxII * prDomainSubBand->ucChannelSpan); + +#if 0 + switch (prChannelEntryField->aucChannelList[u4IdxII]) { + case 1: + ucSocialChnlSupport = 1; + break; + case 6: + ucSocialChnlSupport = 6; + break; + case 11: + ucSocialChnlSupport = 11; + break; + default: + break; + } + +#endif + } + + if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) { + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + else { + break; + } + + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryField->ucNumberOfChannels); + + } + +#if 0 + if (prP2pConnSetting->ucListenChnl == 0) { + prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL; + + if (ucSocialChnlSupport != 0) { + /* 1. User Not Set LISTEN channel. + * 2. Social channel is not empty. + */ + prP2pConnSetting->ucListenChnl = ucSocialChnlSupport; + } + } + +#endif + + // TODO: 20110921 frog - + /* If LISTEN channel is not set, + * a random supported channel would be set. + * If no social channel is supported, DEFAULT channel would be set. + */ + + prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize; + +#if 0 + if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */ + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) { + break; // while + } + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField->ucNumberOfChannels != 0) { + ucAutoChnl = prChannelEntryField->aucChannelList[0]; + break; // while + } + + else { + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + + } + + + + } + +#endif + /* We assume user would not set a channel not in the channel list. + * If so, the operating channel still depends on target deivce supporting capability. + */ + + // TODO: 20110921 frog - + /* If the Operating channel is not set, a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif + return; +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find a common channel list from the local channel list info & target channel list info. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFuncCommonChannelList ( + IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, + IN UINT_8 ucChannelListSize + ) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)NULL, prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)NULL; + UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; + UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0; + + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField; + ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize; + + while (ucOriChnlSize > 0) { + if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) { + prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass; + // TODO: Currently we assume that the regulatory class the same, the channels are the same. + kalMemCopy(prChannelEntryIII->aucChannelList, prChannelEntryII->aucChannelList, prChannelEntryII->ucNumberOfChannels); + prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels; + + ucNewChnlSize += P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryIII->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryI->ucNumberOfChannels); + + + } + + + ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryII->ucNumberOfChannels); + + + } + + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); + + return; +} /* rlmFuncCommonChannelList */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +rlmFuncFindOperatingClass ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucChannelNum + ) +{ + UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)NULL; + UINT_32 u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) { + ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass; + break; + } + + } + + + if (ucRegulatoryClass != 0) { + break; //while + } + else { + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + + } + + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmFuncFindAvailableChannel ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, + IN BOOLEAN fgIsSocialChannel, + IN BOOLEAN fgIsDefaultChannel + ) +{ + BOOLEAN fgIsResultAvailable = FALSE; + P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL; + UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (fgIsDefaultChannel) { + ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL; + } + + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField; + + while ((ucBufferSize != 0) && (!fgIsResultAvailable)) { + + for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) { + if ((!fgIsSocialChannel) || + (prChannelEntry->aucChannelList[ucIdx] == 1) || + (prChannelEntry->aucChannelList[ucIdx] == 6) || + (prChannelEntry->aucChannelList[ucIdx] == 11)) { + + if (prChannelEntry->aucChannelList[ucIdx] <= 11) { + /* 2.4G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } + else if ((prChannelEntry->aucChannelList[ucIdx] < 52) && + (prChannelEntry->aucChannelList[ucIdx] > 14)) { + /* 2.4G + 5G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } + + if (ucChannelSelected == ucCheckChnl) { + fgIsResultAvailable = TRUE; + break; + } + } + + } + + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels); + + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntry->ucNumberOfChannels); + + } + + + + if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) { + DBGLOG(P2P, TRACE, ("The request channel %d is not available, sugguested channel:%d\n", ucCheckChnl, ucChannelSelected)); + // Given a suggested channel. + *pucSuggestChannel = ucChannelSelected; + } + + + } while (FALSE); + + return fgIsResultAvailable; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +ENUM_CHNL_EXT_T +rlmDecideScoForAP ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + UINT_8 ucSecondChannel, i, j; + ENUM_CHNL_EXT_T eSCO; + + eSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) { + eSCO = (prBssInfo->ucPrimaryChannel > 7) ? + CHNL_EXT_SCB : CHNL_EXT_SCA; + } + } + else { + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + if (prSubband->ucBand == prBssInfo->eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j*prSubband->ucChannelSpan) + == prBssInfo->ucPrimaryChannel) { + eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) { + break; /* Found */ + } + } + } + } + + /* Check if it is boundary channel and 40MHz BW is permitted */ + if (eSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eSCO == CHNL_EXT_SCA) ? + (prBssInfo->ucPrimaryChannel+ 4) : (prBssInfo->ucPrimaryChannel- 4); + + if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)){ + eSCO = CHNL_EXT_SCN; + } + } + + return eSCO; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c new file mode 100755 index 000000000000..f9045373157b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c @@ -0,0 +1,374 @@ +/* +** $Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_cfg80211.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + using cfg80211 interface + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +#include "precomp.h" + + +static UINT_8 +rlmObssChnlLevelIn2G4 ( + P_BSS_INFO_T prBssInfo, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ); + +static UINT_8 +rlmObssChnlLevelIn5G ( + P_BSS_INFO_T prBssInfo, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ); + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Different concurrent network has itself channel lists, and +* concurrent networks should have been recorded in channel lists. +* If role of active P2P is GO, assume associated AP of AIS will +* record our Beacon for P2P GO because of same channel. +* +* Note: If we have scenario of different channel in the future, +* the internal FW communication channel shall be established. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +rlmObssChnlLevel ( + P_BSS_INFO_T prBssInfo, + ENUM_BAND_T eBand, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ) +{ + UINT_8 ucChannelLevel; + + ASSERT(prBssInfo); + + if (eBand == BAND_2G4) { + ucChannelLevel = rlmObssChnlLevelIn2G4(prBssInfo, ucPriChannel,eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } + else if (eBand == BAND_5G) { + ucChannelLevel = rlmObssChnlLevelIn5G(prBssInfo, ucPriChannel,eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } + else { + ucChannelLevel = CHNL_LEVEL0; + } + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 +rlmObssChnlLevelIn2G4 ( + P_BSS_INFO_T prBssInfo, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel, ucCenterChannel; + UINT_8 ucAffectedChnl_L, ucAffectedChnl_H; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) { + ucCenterChannel = ucPriChannel + 2; + ucSecChannel = ucPriChannel + 4; + } + else if (eExtend == CHNL_EXT_SCB) { + ucCenterChannel = ucPriChannel - 2; + ucSecChannel = ucPriChannel - 4; + } + else { + return CHNL_LEVEL0; + } + ASSERT(ucCenterChannel >= 1 && ucCenterChannel <= 14); + + /* Calculated low/upper channels in affected freq range */ + ucAffectedChnl_L = (ucCenterChannel <= AFFECTED_CHNL_OFFSET) ? + 1 : (ucCenterChannel - AFFECTED_CHNL_OFFSET); + + ucAffectedChnl_H = (ucCenterChannel >= (14 - AFFECTED_CHNL_OFFSET)) ? + 14 : (ucCenterChannel + AFFECTED_CHNL_OFFSET); + + + /* Check intolerant (Non-HT) channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_NonHtChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_NonHtChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_NonHtChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 20M BW request channel list */ + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_20mReqChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_20mReqChnlList[i] <= ucAffectedChnl_H)) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G primary channel list */ + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_PriChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_PriChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_PriChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G secondary channel list */ + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_SecChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_SecChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_SecChnlList[i] != ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + +L_2G4_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 +rlmObssChnlLevelIn5G ( + P_BSS_INFO_T prBssInfo, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend + ) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) { + ucSecChannel = ucPriChannel + 4; + } + else if (eExtend == CHNL_EXT_SCB) { + ucSecChannel = ucPriChannel - 4; + } + else { + return CHNL_LEVEL0; + } + ASSERT(ucSecChannel >= 36); + + /* Check 5G primary channel list */ + ASSERT(prBssInfo->auc5G_PriChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_PriChnlList[0] && + i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_PriChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } + else if (prBssInfo->auc5G_PriChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check non-HT channel list */ + ASSERT(prBssInfo->auc5G_NonHtChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_NonHtChnlList[0] && + i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_NonHtChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } + else if (prBssInfo->auc5G_NonHtChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check secondary channel list */ + ASSERT(prBssInfo->auc5G_SecChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_SecChnlList[0] && + i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_SecChnlList[i] == ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } + } + +L_5G_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmObssScanExemptionRsp ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb + ) +{ + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + + /* To do: need an algorithm to do judgement. Now always reject request */ + + prMsduInfo = (P_MSDU_INFO_T) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfo == NULL) { + return; + } + + DBGLOG(RLM, INFO, ("Send 20/40 coexistence rsp frame!\n")); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) prMsduInfo->prPacket; + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, + ((P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader)->aucSrcAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = 0; + + ASSERT((WLAN_MAC_HEADER_LEN + 5) <= PUBLIC_ACTION_MAX_LEN); + + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex =prSwRfb->ucStaRecIdx; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_HTC_LEN + 5; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c new file mode 100755 index 000000000000..0639b5384e3f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c @@ -0,0 +1,831 @@ +/* +** $Id: @(#) p2p_scan.c@@ +*/ + +/*! \file "p2p_scan.c" + \brief This file defines the p2p scan profile and the processing function of + scan result for SCAN Module. + + The SCAN Profile selection is part of SCAN MODULE and responsible for defining + SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. + In this file we also define the process of SCAN Result including adding, searching + and removing SCAN record from the list. +*/ + + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucDeviceID[], + IN PP_BSS_DESC_T pprBssDesc + ) +{ + + P_P2P_DEVICE_DESC_T prTargetP2pDesc = (P_P2P_DEVICE_DESC_T)NULL; + P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T)NULL; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + + + ASSERT(prAdapter); + ASSERT(aucDeviceID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + //4 <1> The outer loop to search for a candidate. + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* Loop for each prBssDesc */ + prTargetP2pDesc = scanFindP2pDeviceDesc(prAdapter, + prBssDesc, + aucDeviceID, + TRUE, + FALSE); + + if (prTargetP2pDesc != NULL) { + break; + } + } + + if ((pprBssDesc) && (prTargetP2pDesc != NULL)) { + /* Only valid if prTargetP2pDesc is not NULL. */ + *pprBssDesc = prBssDesc; + } + + return prTargetP2pDesc; +} /* scanSearchTargetP2pDesc */ + + + + +VOID +scanInvalidAllP2pClientDevice ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T)NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (prTargetDesc->fgDevInfoValid) { + prTargetDesc->fgDevInfoValid = FALSE; + } + } + + return; +} /* scanRenewP2pClientDevice */ + +VOID +scanRemoveInvalidP2pClientDevice ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL, prNexEntry = (P_LINK_ENTRY_T)NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + LINK_FOR_EACH_SAFE(prLinkEntry, prNexEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (!prTargetDesc->fgDevInfoValid) { + LINK_REMOVE_KNOWN_ENTRY(&prBssDesc->rP2pDeviceList, prLinkEntry); + if ((prP2pConnSettings) && + (prP2pConnSettings->prTargetP2pDesc == prTargetDesc)) { + prP2pConnSettings->prTargetP2pDesc = NULL; + } + kalMemFree(prTargetDesc, VIR_MEM_TYPE, sizeof(P2P_DEVICE_DESC_T)); + } + } + + return; +} /* scanRenewP2pClientDevice */ + + + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], + IN BOOLEAN fgIsDeviceAddr, + IN BOOLEAN fgAddIfNoFound + ) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T)NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prBssDesc != NULL) && + (aucMacAddr != NULL)); + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (fgIsDeviceAddr) { + if (EQUAL_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr)) { + break; + } + } + else { + if (EQUAL_MAC_ADDR(prTargetDesc->aucInterfaceAddr, aucMacAddr)) { + break; + } + } + + prTargetDesc = NULL; + } + + if ((fgAddIfNoFound) && (prTargetDesc == NULL)) { + /* Target Not Found. */ + // TODO: Use memory pool in the future. + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + } + else { + ASSERT(FALSE); + } + } + + } while (FALSE); + + return prTargetDesc; +} /* scanFindP2pDeviceDesc */ + + +P_P2P_DEVICE_DESC_T +scanGetP2pDeviceDesc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T)NULL; + + ASSERT(prAdapter); + ASSERT(prBssDesc); + + if (prBssDesc->prP2pDesc == NULL) { + + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + prBssDesc->prP2pDesc = prTargetDesc; + /* We are not sure the SrcAddr is Device Address or Interface Address. */ + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, prBssDesc->aucSrcAddr); + COPY_MAC_ADDR(prTargetDesc->aucInterfaceAddr, prBssDesc->aucSrcAddr); + } + else { + + ASSERT(FALSE); + } + } + else { + prTargetDesc = prBssDesc->prP2pDesc; + } + + + return prTargetDesc; + +} /* scanFindP2pDeviceDesc */ + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scanUpdateP2pDeviceDesc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_P2P_DEVICE_DESC_T prP2pDesc = (P_P2P_DEVICE_DESC_T)NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T)NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + BOOLEAN fgUpdateDevInfo = FALSE; + + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T)NULL; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T)NULL; + + ASSERT(prAdapter); + + prP2pDesc = scanGetP2pDeviceDesc(prAdapter, prBssDesc); + + if (!prP2pDesc) { + ASSERT(FALSE); + return fgUpdateDevInfo; + } + + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8)&prP2pAttribute, &u2AttributeLen); + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: /* Beacon, Probe Response */ + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T)NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T)prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + + prP2pDesc->ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + prP2pDesc->ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: /* Beacon */ + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T)NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T)prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == P2P_ATTRI_MAX_LEN_P2P_DEV_ID); + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: /* Probe Response */ + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T)NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T)NULL; + UINT_16 u2NameLen = 0, u2Id = 0; + + fgUpdateDevInfo = TRUE; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T)prP2pAttribute; + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevInfo->aucDevAddr, MAC_ADDR_LEN); + + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &prP2pDesc->rPriDevType; + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId, &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId, &prP2pDevType->u2SubCategoryID); + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); // TODO: Fixme if secondary device type is more than 2. + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->arSecondaryDevTypeListBE[u4Idx].u2CategoryId, &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = (P_DEVICE_NAME_TLV_T)((PUINT_8)prP2pAttriDevInfo->arSecondaryDevTypeListBE + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &u2NameLen); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Id, &u2Id); + ASSERT(u2Id == WPS_ATTRI_ID_DEVICE_NAME); + if (u2NameLen > WPS_ATTRI_MAX_LEN_DEVICE_NAME) { + u2NameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + } + prP2pDesc->u2NameLength = u2NameLen; + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: /* Probe Response */ + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T)prP2pAttribute; + break; + case P2P_ATTRI_ID_NOTICE_OF_ABSENCE: + break; + case P2P_ATTRI_ID_EXT_LISTEN_TIMING: + // TODO: Not implement yet. + //ASSERT(FALSE); + break; + default: + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = (P_P2P_ATTRIBUTE_T)((UINT_32)prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T)NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T)NULL; + + scanInvalidAllP2pClientDevice(prAdapter, prBssDesc); + + /* GO/Device itself. */ + prP2pDesc->fgDevInfoValid = TRUE; + + prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T)prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + + while (u2AttributeLen > 0) { + prP2pDesc = scanFindP2pDeviceDesc(prAdapter, prBssDesc, prClientInfoDesc->aucDevAddr, TRUE, TRUE); + + if (!prP2pDesc) { + ASSERT(FALSE); + break; /* while */ + } + + prP2pDesc->fgDevInfoValid = TRUE; + + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + if (u2AttributeLen < 25) { + DBGLOG(P2P, WARN, ("Length incorrect warning.\n")); + break; + } + COPY_MAC_ADDR(prP2pDesc->aucInterfaceAddr, prClientInfoDesc->aucIfAddr); + + prP2pDesc->ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + + WLAN_GET_FIELD_BE16(&prClientInfoDesc->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &(prP2pDesc->rPriDevType); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId, &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId, &prP2pDevType->u2SubCategoryID); + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2CategoryId, &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = (P_DEVICE_NAME_TLV_T)(prClientInfoDesc->arSecondaryDevTypeListBE + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &prP2pDesc->u2NameLength); + if (prP2pDesc->u2NameLength > WPS_ATTRI_MAX_LEN_DEVICE_NAME) { + prP2pDesc->u2NameLength = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + } + + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + + u2AttributeLen -= (prClientInfoDesc->ucLength + P2P_CLIENT_INFO_DESC_HDR_LEN); + prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T)((UINT_32)prClientInfoDesc + (UINT_32)prClientInfoDesc->ucLength + P2P_CLIENT_INFO_DESC_HDR_LEN); + } + + scanRemoveInvalidP2pClientDevice(prAdapter, prBssDesc); + } + + return fgUpdateDevInfo; +} /* end of scanAddP2pDeviceInfo() */ + +#endif + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +scanSendDeviceDiscoverEvent ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_SW_RFB_T prSwRfb + ) +{ + EVENT_P2P_DEV_DISCOVER_RESULT_T rEventDevInfo; +#if 1 + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T)NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T)NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + COPY_MAC_ADDR(rEventDevInfo.aucDeviceAddr, prTargetDesc->aucDeviceAddr); + COPY_MAC_ADDR(rEventDevInfo.aucInterfaceAddr, prTargetDesc->aucInterfaceAddr); + + rEventDevInfo.ucDeviceCapabilityBitmap = prTargetDesc->ucDeviceCapabilityBitmap; + rEventDevInfo.ucGroupCapabilityBitmap = prTargetDesc->ucGroupCapabilityBitmap; + rEventDevInfo.u2ConfigMethod = prTargetDesc->u2ConfigMethod; + + kalMemCopy(&rEventDevInfo.rPriDevType, + &prTargetDesc->rPriDevType, + sizeof(P2P_DEVICE_TYPE_T)); + + kalMemCopy(rEventDevInfo.arSecDevType, + prTargetDesc->arSecDevType, + (prTargetDesc->ucSecDevTypeNum * sizeof(P2P_DEVICE_TYPE_T))); + + rEventDevInfo.ucSecDevTypeNum = prTargetDesc->ucSecDevTypeNum; + + rEventDevInfo.u2NameLength = prTargetDesc->u2NameLength; + kalMemCopy(rEventDevInfo.aucName, + prTargetDesc->aucName, + prTargetDesc->u2NameLength); + + COPY_MAC_ADDR(rEventDevInfo.aucBSSID, prBssDesc->aucBSSID); + + if (prTargetDesc == prBssDesc->prP2pDesc) { + nicRxAddP2pDevice(prAdapter, + &rEventDevInfo, + prBssDesc->aucIEBuf, + prBssDesc->u2IELength); + } + else { + nicRxAddP2pDevice(prAdapter, + &rEventDevInfo, + NULL, + 0); + } + } + + kalP2PIndicateFound(prAdapter->prGlueInfo); + +#else + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T)NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T)NULL; + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T)NULL; + + ASSERT(prAdapter); + + prP2pSpecificBssInfo = &prAdapter->rWifiVar.rP2pSpecificBssInfo; + +#if 1 + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8)&prP2pAttribute, &u2AttributeLen); +#else + prP2pAttribute = (P_P2P_ATTRIBUTE_T)&prP2pSpecificBssInfo->aucAttributesCache[0]; + u2AttributeLen = prP2pSpecificBssInfo->u2AttributeLen; +#endif + rEventDevInfo.fgDevInfoValid = FALSE; + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T)NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T)prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + rEventDevInfo.ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + rEventDevInfo.ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T)NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T)prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == 6); + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T)NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T)NULL; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T)prP2pAttribute; + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevInfo->aucDevAddr, MAC_ADDR_LEN); + rEventDevInfo.u2ConfigMethod = prP2pAttriDevInfo->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= 2); // TODO: Fixme if secondary device type is more than 2. + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + // TODO: Current sub device type can only support 2. + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + } + + prP2pDevName = (P_DEVICE_NAME_TLV_T)(prP2pAttriDevInfo->arSecondaryDevTypeListBE + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); // TODO: Fixme if device name length is longer than 32 bytes. + kalMemCopy(rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T)prP2pAttribute; + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = (P_P2P_ATTRIBUTE_T)((UINT_32)prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + nicRxAddP2pDevice(prAdapter, + &rEventDevInfo); + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T)NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T)NULL; + + prClientInfoDesc = prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + while (u2AttributeLen > 0) { + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prClientInfoDesc->aucIfAddr, MAC_ADDR_LEN); + rEventDevInfo.ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + rEventDevInfo.u2ConfigMethod = prClientInfoDesc->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= 2); // TODO: Fixme if secondary device type is more than 2. + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + // TODO: Current sub device type can only support 2. + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2CategoryId; + prP2pDevType->u2SubCategoryID = prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId; + } + + prP2pDevName = (P_DEVICE_NAME_TLV_T)(prClientInfoDesc->arSecondaryDevTypeListBE + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); // TODO: Fixme if device name length is longer than 32 bytes. + kalMemCopy(&rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + + nicRxAddP2pDevice(prAdapter, + &rEventDevInfo); + + u2AttributeLen -= prP2pAttriGroupInfo->u2Length; + prP2pAttriGroupInfo = prP2pAttriGroupInfo + prP2pAttriGroupInfo->u2Length + 1; + } + + } +#endif + return WLAN_STATUS_SUCCESS; +} /* scanSendDeviceDiscoverEvent */ + +VOID +scanP2pProcessBeaconAndProbeResp( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, + IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prBssDesc->fgIsP2PPresent) { + + if ((!prP2pBssInfo->ucDTIMPeriod) && // First time. + (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && // P2P GC + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && // Connected + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON) && // TX Beacon + EQUAL_SSID(prBssDesc->aucSSID, // SSID Match + prBssDesc->ucSSIDLen, + prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen)) { + + + prP2pBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + do { + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); + + if (((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) != MAC_FRAME_PROBE_RSP)) { + // Only report Probe Response frame to supplicant. + /* Probe response collect much more information. */ + break; + } + + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8)prSwRfb->pvHeader, + (UINT_32)prSwRfb->u2PacketLen, + &rChannelInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + + + } while (FALSE); + } +} + +VOID +scnEventReturnChannel ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucScnSeqNum + ) +{ + + CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SCAN_CANCEL), + (PUINT_8)&rCmdScanCancel, + NULL, + 0); + + return; +} /* scnEventReturnChannel */ + +VOID +scanRemoveAllP2pBssDesc( + IN P_ADAPTER_T prAdapter + ) +{ + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +VOID +scanRemoveP2pBssDesc( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + + return; +} /* scanRemoveP2pBssDesc */ + + +P_BSS_DESC_T +scanP2pSearchDesc ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo + ) +{ + P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T)NULL, prBssDesc = (P_BSS_DESC_T)NULL; + P_LINK_T prBssDescList = (P_LINK_T)NULL; + + do { + if ((prAdapter == NULL) || + (prP2pBssInfo == NULL) || + (prConnReqInfo == NULL)) { + break; + } + + + prBssDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + DBGLOG(P2P, LOUD, ("Connecting to BSSID: "MACSTR"\n", MAC2STR(prConnReqInfo->aucBssid))); + DBGLOG(P2P, LOUD, ("Connecting to SSID:%s, length:%d\n", + prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen)); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBssDescList, rLinkEntry, BSS_DESC_T) { + DBGLOG(P2P, LOUD, ("Checking BSS: "MACSTR"\n", MAC2STR(prBssDesc->aucBSSID))); + + if (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) { + DBGLOG(P2P, LOUD, ("Ignore mismatch BSS type.\n")); + continue; + } + + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnReqInfo->aucBssid)) { + DBGLOG(P2P, LOUD, ("Ignore mismatch BSSID.\n")); + continue; + } + + + /* SSID should be the same? SSID is vary for each connection. so... */ + if (UNEQUAL_SSID(prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen)) { + + DBGLOG(P2P, TRACE, ("Connecting to BSSID: "MACSTR"\n", MAC2STR(prConnReqInfo->aucBssid))); + DBGLOG(P2P, TRACE, ("Connecting to SSID:%s, length:%d\n", + prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen)); + DBGLOG(P2P, TRACE, ("Checking SSID:%s, length:%d\n", + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen)); + DBGLOG(P2P, TRACE, ("Ignore mismatch SSID, (But BSSID match).\n")); + ASSERT(FALSE); + continue; + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c new file mode 100755 index 000000000000..64b9ae62aaf9 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c @@ -0,0 +1,577 @@ +#include "p2p_precomp.h" + + +BOOLEAN +p2pStateInit_IDLE ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + OUT P_ENUM_P2P_STATE_T peNextState + ) +{ + BOOLEAN fgIsTransOut = FALSE; +// P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && + (prP2pBssInfo != NULL) && + (peNextState != NULL)); + + if ((prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) && IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + fgIsTransOut = TRUE; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + *peNextState = P2P_STATE_REQING_CHANNEL; + + } + else { +#if 0 + else if (IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + + ASSERT((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)); + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + /* Start a timer for return channel. */ + DBGLOG(P2P, TRACE, ("start a GO channel timer.\n")); + } + + } + +#endif + cnmTimerStartTimer(prAdapter, &(prP2pFsmInfo->rP2pFsmTimeoutTimer), 5000); + } + + } while (FALSE); + + return fgIsTransOut; +} /* p2pStateInit_IDLE */ + + +VOID +p2pStateAbort_IDLE ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + + if (prChnlReqInfo->fgIsChannelRequested) { + /* Release channel before timeout. */ + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } + + + /* Stop timer for leaving this state. */ + cnmTimerStopTimer(prAdapter, &(prP2pFsmInfo->rP2pFsmTimeoutTimer)); + + } while (FALSE); + + return; +} /* p2pStateAbort_IDLE */ + + + +VOID +p2pStateInit_CHNL_ON_HAND ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Store the original channel info. */ + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + /* RX Probe Request would check primary channel.*/ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + + DBGLOG(P2P, TRACE, ("start a channel on hand timer.\n")); + cnmTimerStartTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + prChnlReqInfo->u4MaxInterval); + + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + + } while (FALSE); + + return; +} /* p2pStateInit_CHNL_ON_HAND */ + + +VOID +p2pStateAbort_CHNL_ON_HAND ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prP2pFsmInfo->rP2pFsmTimeoutTimer)); + + /* Restore the original channel info. */ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + if (eNextState != P2P_STATE_CHNL_ON_HAND) { + /* Indicate channel return. */ + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); + + // Return Channel. + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + } while (FALSE); + return; +} /* p2pStateAbort_CHNL_ON_HAND */ + + +VOID +p2pStateAbort_REQING_CHANNEL ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && + (eNextState < P2P_STATE_NUM)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (eNextState == P2P_STATE_IDLE) { + if (prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) { + /* Intend to be AP. */ + /* Setup for AP mode. */ + p2pFuncStartGO(prAdapter, + prP2pBssInfo, + prP2pSpecificBssInfo->aucGroupSsid, + prP2pSpecificBssInfo->u2GroupSsidLen, + prP2pSpecificBssInfo->ucPreferredChannel, + prP2pSpecificBssInfo->eRfBand, + prP2pSpecificBssInfo->eRfSco, + prP2pFsmInfo->fgIsApMode); + + } + else { + // Return Channel. + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + } + + + } while (FALSE); + + return; +} /* p2pStateInit_AP_CHANNEL_DETECT */ + + +VOID +p2pStateInit_AP_CHANNEL_DETECT ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + prScanReqInfo->u2PassiveDewellTime = 50; // 50ms for passive channel load detection + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + + return; +} /* p2pStateInit_AP_CHANNEL_DETECT */ + + + +VOID +p2pStateAbort_AP_CHANNEL_DETECT ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + do { + + if (eNextState == P2P_STATE_REQING_CHANNEL) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Determine the channel for AP. */ + if (cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) { + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if ((ucPreferedChnl = prP2pConnSettings->ucOperatingChnl) == 0) { + + if (scnQuerySparseChannel(prAdapter, &eBand, &ucPreferedChnl) == FALSE) { + + // What to do? + ASSERT(FALSE); + // TODO: Pick up a valid channel from channel list. + ucPreferedChnl = 1; + eBand = BAND_2G4; + } + } + } + + + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand = eBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco = eSco; + } + else { + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + } + + + } while (FALSE); + + return; +} /* p2pStateAbort_AP_CHANNEL_DETECT */ + + +VOID +p2pStateInit_SCAN ( + + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo + ) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T)NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &prP2pFsmInfo->rScanReqInfo; + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + return; +} /* p2pStateInit_SCAN */ + + +VOID +p2pStateAbort_SCAN ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + do { + ASSERT_BREAK(prAdapter != NULL); + + // 1. Scan cancel. (Make sure the scan request is invalid. + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + + // Scan done indication. + kalP2PIndicateScanDone(prAdapter->prGlueInfo, prP2pFsmInfo->rScanReqInfo.fgIsAbort); + } while (FALSE); + + return; +} /* p2pStateAbort_SCAN */ + + +VOID +p2pStateInit_GC_JOIN ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T)NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && + (prP2pBssInfo != NULL) && + (prJoinInfo != NULL) && + (prBssDesc != NULL)); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + + + // Setup a join timer. + DBGLOG(P2P, TRACE, ("Start a join init timer\n")); + cnmTimerStartTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + (prP2pFsmInfo->u4GrantInterval - AIS_JOIN_CH_GRANT_THRESHOLD)); + + //2 <1> We are goin to connect to this BSS + prBssDesc->fgIsConnecting = TRUE; + + //2 <2> Setup corresponding STA_RECORD_T + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + (prBssDesc->fgIsP2PPresent?(STA_TYPE_P2P_GO):(STA_TYPE_LEGACY_AP)), + NETWORK_TYPE_P2P_INDEX, + prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, ("Create station record fail\n")); + break; + } + + + prJoinInfo->prTargetStaRec = prStaRec; + prJoinInfo->fgIsJoinComplete = FALSE; + prJoinInfo->u4BufLength = 0; + + //2 <2.1> Sync. to FW domain + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + prStaRec->fgIsReAssoc = FALSE; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + switch (prP2pConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: /* Note: Omit break here. */ + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + prJoinInfo->ucAvailableAuthTypes = (UINT_8)AUTH_TYPE_OPEN_SYSTEM; + break; + case AUTH_MODE_SHARED: + prJoinInfo->ucAvailableAuthTypes = (UINT_8)AUTH_TYPE_SHARED_KEY; + break; + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(P2P, LOUD, ("JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n")); + prJoinInfo->ucAvailableAuthTypes = (UINT_8)(AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SHARED_KEY); + break; + default: + ASSERT(!(prP2pConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); + DBGLOG(P2P, ERROR, ("JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", + prP2pConnSettings->eAuthMode)); + /* TODO(Kevin): error handling ? */ + return; + } + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + } + else { + ASSERT(FALSE); + // TODO: Shall we considering ROAMIN case for P2P Device?. + } + + + //2 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes. + if (prJoinInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, ("JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n")); + + prJoinInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } + else if (prJoinInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, TRACE, ("JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n")); + + prJoinInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_SHARED_KEY; + } + else if (prJoinInfo->ucAvailableAuthTypes & + (UINT_8)AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(P2P, TRACE, ("JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n")); + + prJoinInfo->ucAvailableAuthTypes &= + ~(UINT_8)AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = (UINT_8)AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } + else { + ASSERT(0); + } + + + //4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prJoinInfo->rSsidStruct.aucSsid, + prJoinInfo->rSsidStruct.ucSsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + + //2 <5> Backup desired channel. + + //2 <6> Send a Msg to trigger SAA to start JOIN process. + prJoinReqMsg = (P_MSG_JOIN_REQ_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + + if (!prJoinReqMsg) { + DBGLOG(P2P, TRACE, ("Allocation Join Message Fail\n")); + ASSERT(FALSE); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + // TODO: Consider fragmentation info in station record. + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + + + + } while (FALSE); + + return; +} /* p2pStateInit_GC_JOIN */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort. Leave JOIN State & Abort JOIN. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pStateAbort_GC_JOIN ( + IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, + IN ENUM_P2P_STATE_T eNextState + ) +{ + P_MSG_JOIN_ABORT_T prJoinAbortMsg = (P_MSG_JOIN_ABORT_T)NULL; + + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (prJoinInfo != NULL)); + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + + prJoinAbortMsg = (P_MSG_JOIN_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + DBGLOG(P2P, TRACE, ("Fail to allocate join abort message buffer\n")); + ASSERT(FALSE); + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prJoinInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prJoinInfo->prTargetStaRec; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prJoinAbortMsg, + MSG_SEND_METHOD_BUF); + + } + + /* Stop Join Timer. */ + cnmTimerStopTimer(prAdapter, &(prP2pFsmInfo->rP2pFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + + } while (FALSE); + + return; + +} /* p2pStateAbort_GC_JOIN */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c new file mode 100755 index 000000000000..66b33a631b71 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c @@ -0,0 +1,1024 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/privacy.c#1 $ +*/ + +/*! \file "privacy.c" + \brief This file including the protocol layer privacy function. + + This file provided the macros and functions library support for the + protocol layer security setting from rsn.c and nic_privacy.c + +*/ + + + +/* +** $Log: privacy.c $ + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 20 2011 terry.wu + * NULL + * Fix Hotspot deauth send failed. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 28 2011 tsaiyuan.hsu + * [WCXRP00000819] [MT6620 Wi-Fi][Driver] check if staRec is NULL or not in secCheckClassError + * check if staRec is NULL or not in secCheckClassError. + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * adding the compiling flag for migration. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 04 22 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the wpi same key id rx issue and fixed the remove wep key issue. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * remove the assert code for allow ad-hoc pkt. + * + * 04 13 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the Klocwork error and refine the class error message. + * + * 03 04 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Code refine, and remove non-used code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 26 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * change the waning message shown level, and clear the global transmit flag for CMD INFRASTRUCTURE. + * + * 02 25 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * For support the WHQL test, do the remove key code refine. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * * * * * * * * MQM: BA handling + * * * * * * * * * TXM: Macros updates + * * * * * * * * * RXM: Macros/Duplicate Removal updates + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 11 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * modify the cmd with result return + * + * Dec 11 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * fixed the value not initialize issue + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the cmd return type + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function to update the auth mode and encryption status for cmd build connection + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some code for wapi mode + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the call to check the 4th and eapol error report frame + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the function name + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code for parsing the EAPoL frame, and do some code refine + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the class error check + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the cmd_802_11_pmkid code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * doing some function rename, and adding the code for cmd CMD_ADD_REMOVE_KEY + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the clear pmkid function + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix eStaType check for AIS + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the ap selection related code + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_PRIVACY_MIGRATION + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to initialize the privacy-related +* parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucNetTypeIdx Pointer to netowrk type index +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +secInit ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucNetTypeIdx + ) +{ + UINT_8 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("secInit"); + + ASSERT(prAdapter); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prBssInfo->u4RsnSelectedGroupCipher = 0; + prBssInfo->u4RsnSelectedPairwiseCipher = 0; + prBssInfo->u4RsnSelectedAKMSuite = 0; + +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[0].dot11RSNAConfigPairwiseCipher = + WPA_CIPHER_SUITE_WEP40; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[1].dot11RSNAConfigPairwiseCipher = + WPA_CIPHER_SUITE_TKIP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[2].dot11RSNAConfigPairwiseCipher = + WPA_CIPHER_SUITE_CCMP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[3].dot11RSNAConfigPairwiseCipher = + WPA_CIPHER_SUITE_WEP104; + + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[4].dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_WEP40; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[5].dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_TKIP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[6].dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_CCMP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[7].dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_WEP104; + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i ++) { + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = + FALSE; + } + + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[0].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_NONE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[1].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[2].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_PSK; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[3].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_NONE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[4].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[5].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_PSK; + +#if CFG_SUPPORT_802_11W + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[6].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X_SHA256; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[7].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_PSK_SHA256; +#endif + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i ++) { + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i].dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + + secClearPmkid(prAdapter); + + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnIndicatePmkidCand, + (UINT_32)NULL); + +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnStartSaQueryTimer, + (UINT_32)NULL); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prAisSpecBssInfo->ucWEPDefaultKeyID = 0; + + + #if 0 + for (i=0;iarWtbl[i].fgUsed = FALSE; + g_prWifiVar->arWtbl[i].prSta = NULL; + g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; + + } + nicPrivacyInitialize((UINT_8)NETWORK_TYPE_INDEX_NUM); + #endif +} /* secInit */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Rx Class Error" to SEC_FSM for +* JOIN Module. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSwRfb Pointer to the SW RFB. +* +* \return FALSE Class Error +*/ +/*----------------------------------------------------------------------------*/ +BOOL +secCheckClassError ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_STA_RECORD_T prStaRec + ) +{ + ASSERT(prAdapter); + ASSERT(prSwRfb); + //ASSERT(prStaRec); + + //prStaRec = &(g_arStaRec[prSwRfb->ucStaRecIdx]); + + if ((prStaRec) && 1 /* RXM_IS_DATA_FRAME(prSwRfb) */) { + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = prStaRec->ucNetTypeIndex; + + if (IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) { + P_BSS_INFO_T prBssInfo; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]; + + if ((STA_STATE_3 != prStaRec->ucStaState) && + IS_BSS_ACTIVE(prBssInfo) && + prBssInfo->fgIsNetAbsent == FALSE) { + /*(IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) {*/ + + if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, + prStaRec, + NULL, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER)NULL)) { + + DBGLOG(RSN, INFO, ("Send Deauth to MAC:["MACSTR"] for Rx Class 3 Error.\n", + MAC2STR(prStaRec->aucMacAddr))); + } + + return FALSE; + } + + return secRxPortControlCheck(prAdapter, prSwRfb); + } + } + + return FALSE; +} /* end of secCheckClassError() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to setting the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[in] fgPortBlock The port status +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +secSetPortBlocked ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + IN BOOLEAN fgPortBlock + ) +{ + if (prSta == NULL) + return ; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, ("The STA "MACSTR" port %s\n", MAC2STR(prSta->aucMacAddr), fgPortBlock == TRUE ? "BLOCK" :" OPEN")); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to report the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[out] fgPortBlock The port status +* +* \return TRUE sta exist, FALSE sta not exist +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secGetPortStatus ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + OUT PBOOLEAN pfgPortStatus + ) +{ + if (prSta == NULL) + return FALSE; + + *pfgPortStatus = prSta->fgPortBlock; + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle Peer device Tx Security process MSDU. +* +* \param[in] prMsduInfo pointer to the packet info pointer +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port blocked +* +*/ +/*----------------------------------------------------------------------------*/ +BOOL /* ENUM_PORT_CONTROL_RESULT */ +secTxPortControlCheck( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec + ) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + if (prStaRec) { + + /* Todo:: */ + if (prMsduInfo->fgIs802_1x) + return TRUE; + + if (prStaRec->fgPortBlock == TRUE) { + DBGLOG(INIT, TRACE, ("Drop Tx packet due Port Control!\n")); + return FALSE; + } + +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + return TRUE; + } +#endif + if (IS_STA_IN_AIS(prStaRec)) { + if (!prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist && + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED)){ + DBGLOG(INIT, TRACE, ("Drop Tx packet due the key is removed!!!\n")); + return FALSE; + } + } + } + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The Rx Security process MSDU. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSWRfb SW rfb pinter +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secRxPortControlCheck ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSWRfb + ) +{ + ASSERT(prSWRfb); + +#if 0 + /* whsu:Todo: Process MGMT and DATA */ + if (prSWRfb->prStaRec) { + if (prSWRfb->prStaRec->fgPortBlock == TRUE) { + if (1 /* prSWRfb->fgIsDataFrame and not 1x*/ && + (g_prWifiVar->rConnSettings.eAuthMode >= AUTH_MODE_WPA)){ + //DBGLOG(SEC, WARN, ("Drop Rx data due port control !\r\n")); + return TRUE; /* Todo: whsu FALSE; */ + } + //if (!RX_STATUS_IS_PROTECT(prSWRfb->prRxStatus)) { + // DBGLOG(RSN, WARN, ("Drop rcv non-encrypted data frame!\n")); + // return FALSE; + //} + } + } + else { + } +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will enable/disable the cipher suite +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4CipherSuitesFlags flag for cipher suite +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +secSetCipherSuite ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4CipherSuitesFlags + ) +{ + UINT_32 i; + P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; + P_IEEE_802_11_MIB_T prMib; + + ASSERT(prAdapter); + + prMib = &prAdapter->rMib; + + ASSERT(prMib); + + if (u4CipherSuitesFlags == CIPHER_FLAG_NONE) { + /* Disable all the pairwise cipher suites. */ + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prMib->dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = + FALSE; + } + + /* Update the group cipher suite. */ + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + + return; + } + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = &prMib->dot11RSNAConfigPairwiseCiphersTable[i]; + + switch (prEntry->dot11RSNAConfigPairwiseCipher) { + case WPA_CIPHER_SUITE_WEP40: + case RSN_CIPHER_SUITE_WEP40: + if (u4CipherSuitesFlags & CIPHER_FLAG_WEP40) { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + } + else { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + } + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (u4CipherSuitesFlags & CIPHER_FLAG_TKIP) { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + } + else { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + } + break; + + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (u4CipherSuitesFlags & CIPHER_FLAG_CCMP) { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + } + else { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + } + break; + + case WPA_CIPHER_SUITE_WEP104: + case RSN_CIPHER_SUITE_WEP104: + if (u4CipherSuitesFlags & CIPHER_FLAG_WEP104) { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + } + else { + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + } + break; + default: + break; + } + } + + /* Update the group cipher suite. */ + if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) { + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_CCMP; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) { + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_TKIP; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) { + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP104; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) { + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP40; + } + else { + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + } + +} /* secSetCipherSuite */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The 2nd Tx EAPoL Frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsduInfo pointer to the packet info pointer +* \param[in] pucPayload pointer to the 1x hdr +* \param[in] u2PayloadLen the 1x payload length +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +* +*/ +/*----------------------------------------------------------------------------*/ +BOOL +secProcessEAPOL ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucPayload, + IN UINT_16 u2PayloadLen +) +{ + P_EAPOL_KEY prEapol = (P_EAPOL_KEY)NULL; + P_IEEE_802_1X_HDR pr1xHdr; + UINT_16 u2KeyInfo; + + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + //prStaRec = &(g_arStaRec[prMsduInfo->ucStaRecIndex]); + ASSERT(prStaRec); + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR)pucPayload; + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY)((PUINT_32)(pucPayload + 4)); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (u2KeyInfo & WPA_KEY_INFO_SECURE) { + /* 4th EAPoL check at secHandleTxDoneCallback() */ + //DBGLOG(RSN, TRACE, ("Tx 4th EAPoL frame\r\n")); + } + else if (u2PayloadLen == 123 /* Not include LLC */) { + DBGLOG(RSN, INFO, ("Tx 2nd EAPoL frame\r\n")); + secFsmEvent2ndEapolTx(prAdapter, prStaRec); + } + } + } + } + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will handle the 4th EAPoL Tx done and mic Error Report frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secHandleTxDoneCallback( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec, + IN WLAN_STATUS rStatus + ) +{ + PUINT_8 pucPayload; + P_IEEE_802_1X_HDR pr1xHdr = (P_IEEE_802_1X_HDR)NULL; + P_EAPOL_KEY prEapol = (P_EAPOL_KEY)NULL; + UINT_16 u2KeyInfo; + UINT_16 u2PayloadLen; + + DEBUGFUNC("secHandleTxDoneCallback"); + + ASSERT(prMsduInfo); + //Todo:: Notice if using the TX free immediate after send to firmware, the payload may not correcttly!!!! + + ASSERT(prStaRec); + + //Todo:: This call back may not need because the order of set key and send 4th 1x can be make sure + //Todo:: Notice the LLC offset + #if 1 + pucPayload = (PUINT_8)prMsduInfo->prPacket; + ASSERT(pucPayload); + + u2PayloadLen = prMsduInfo->u2FrameLength; + + if (0 /* prMsduInfo->fgIs1xFrame */) { + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR)(PUINT_32)(pucPayload + 8); + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY)(PUINT_32)(pucPayload + 12); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (prStaRec->rSecInfo.fg2nd1xSend == TRUE && u2PayloadLen == 107 /* include LLC *//* u2KeyInfo & WPA_KEY_INFO_SECURE */) { + DBGLOG(RSN, INFO, ("Tx 4th EAPoL frame\r\n")); + secFsmEvent4ndEapolTxDone(prAdapter, prStaRec); + } + else if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone){ + DBGLOG(RSN, INFO, ("Tx EAPoL Error report frame\r\n")); + //secFsmEventEapolTxDone(prAdapter, (UINT_32)prMsduInfo->prStaRec); + } + } + } + } + + } + #endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to initialize the pmkid parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +secClearPmkid ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("secClearPmkid"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + DBGLOG(RSN, TRACE, ("secClearPmkid\n")); + prAisSpecBssInfo->u4PmkidCandicateCount = 0; + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero((PVOID)prAisSpecBssInfo->arPmkidCandicate, sizeof(PMKID_CANDICATE_T) * CFG_MAX_PMKID_CACHE); + kalMemZero((PVOID)prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether WPA, or WPA2 but not WPA-None is enabled. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secRsnKeyHandshakeEnabled ( + IN P_ADAPTER_T prAdapter + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + ASSERT(prConnSettings); + + ASSERT(prConnSettings->eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) { + return FALSE; + } + + ASSERT(prConnSettings->eAuthMode < AUTH_MODE_NUM); + if ((prConnSettings->eAuthMode >= AUTH_MODE_WPA) && + (prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) { + return TRUE; + } + + return FALSE; +} /* secRsnKeyHandshakeEnabled */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return whether the transmit key alread installed. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer the sta record +* +* \retval TRUE Default key or Transmit key installed +* FALSE Default key or Transmit key not installed +* +* \note: +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secTransmitKeyExist ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + ASSERT(prSta); + + if (prSta->fgTransmitKeyExist){ + return TRUE; + } + else { + return FALSE; + } +} /* secTransmitKeyExist */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether 802.11 privacy is enabled. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secEnabledInAis ( + IN P_ADAPTER_T prAdapter + ) +{ + DEBUGFUNC("secEnabled"); + + ASSERT(prAdapter->rWifiVar.rConnSettings.eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION_DISABLED: + return FALSE; + case ENUM_ENCRYPTION1_ENABLED: + case ENUM_ENCRYPTION2_ENABLED: + case ENUM_ENCRYPTION3_ENABLED: + return TRUE; + default: + DBGLOG(RSN, TRACE, ("Unknown encryption setting %d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus)); + break; + } + return FALSE; +} /* secEnabled */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the privacy bit at mac header for TxM +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsdu the msdu for known the sta record +* +* \return TRUE the privacy need to set +* FALSE the privacy no need to set +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secIsProtectedFrame ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsdu, + IN P_STA_RECORD_T prStaRec + ) +{ + ASSERT(prAdapter); + + ASSERT(prMsdu); + + ASSERT(prStaRec); + //prStaRec = &(g_arStaRec[prMsdu->ucStaRecIndex]); + + if (prStaRec == NULL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) + return TRUE; + return FALSE; /* No privacy bit */ + } + + /* Todo:: */ + if (0 /* prMsdu->fgIs1xFrame */){ + if (IS_STA_IN_AIS(prStaRec) && + prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + DBGLOG(RSN, LOUD, ("For AIS Legacy 1x, always not encryped\n")); + return FALSE; + } + else if (!prStaRec->fgTransmitKeyExist) { + DBGLOG(RSN, LOUD, ("1x Not Protected.\n")); + return FALSE; + } + else if (prStaRec->rSecInfo.fgKeyStored) { + DBGLOG(RSN, LOUD, ("1x not Protected due key stored!\n")); + return FALSE; + } + else { + DBGLOG(RSN, LOUD, ("1x Protected.\n")); + return TRUE; + } + } + else { + if (!prStaRec->fgTransmitKeyExist) { + /* whsu , check for AIS only */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist){ + DBGLOG(RSN, LOUD, ("Protected\n")); + return TRUE; + } + } + else { + DBGLOG(RSN, LOUD, ("Protected.\n")); + return TRUE; + } + } + + /* No sec or key is removed!!! */ + return FALSE; +} +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c new file mode 100755 index 000000000000..c63fe7b7d641 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c @@ -0,0 +1,547 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rate.c#1 $ +*/ + +/*! \file "rate.c" + \brief This file contains the transmission rate handling routines. + + This file contains the transmission rate handling routines for setting up + ACK/CTS Rate, Highest Tx Rate, Lowest Tx Rate, Initial Tx Rate and do + conversion between Rate Set and Data Rates. +*/ + + + +/* +** $Log: rate.c $ + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add rate.c. + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comments + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix DBGLOG + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** \main\maintrunk.MT5921\12 2008-12-19 17:19:32 GMT mtk01461 +** Fix the problem that do not ASSERT the length of Supported Rate IE == 8 +** \main\maintrunk.MT5921\11 2008-12-01 18:17:42 GMT mtk01088 +** fixed the lint "possible using null pointer" warning +** \main\maintrunk.MT5921\10 2008-08-20 00:16:36 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\9 2008-04-13 21:17:13 GMT mtk01461 +** Revise GEN Link Speed OID +** \main\maintrunk.MT5921\8 2008-03-28 10:40:13 GMT mtk01461 +** Add rateGetRateSetFromDataRates() for set desired rate OID +** \main\maintrunk.MT5921\7 2008-03-26 09:16:20 GMT mtk01461 +** Add adopt operational rate as ACK rate if BasicRateSet was not found +** Add comments +** \main\maintrunk.MT5921\6 2008-02-21 15:01:39 GMT mtk01461 +** Add initial rate according rx signal quality support +** \main\maintrunk.MT5921\5 2008-01-07 15:06:44 GMT mtk01461 +** Fix typo of rate adaptation of CtrlResp Frame +** \main\maintrunk.MT5921\4 2007-10-25 18:05:12 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* The list of valid data rates. */ +const UINT_8 aucDataRate[] = { + RATE_1M, /* RATE_1M_INDEX = 0 */ + RATE_2M, /* RATE_2M_INDEX */ + RATE_5_5M, /* RATE_5_5M_INDEX */ + RATE_11M, /* RATE_11M_INDEX */ + RATE_22M, /* RATE_22M_INDEX */ + RATE_33M, /* RATE_33M_INDEX */ + RATE_6M, /* RATE_6M_INDEX */ + RATE_9M, /* RATE_9M_INDEX */ + RATE_12M, /* RATE_12M_INDEX */ + RATE_18M, /* RATE_18M_INDEX */ + RATE_24M, /* RATE_24M_INDEX */ + RATE_36M, /* RATE_36M_INDEX */ + RATE_48M, /* RATE_48M_INDEX */ + RATE_54M, /* RATE_54M_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const UINT_8 aucDefaultAckCtsRateIndex[RATE_NUM] = { + RATE_1M_INDEX, /* RATE_1M_INDEX = 0 */ + RATE_2M_INDEX, /* RATE_2M_INDEX */ + RATE_5_5M_INDEX, /* RATE_5_5M_INDEX */ + RATE_11M_INDEX, /* RATE_11M_INDEX */ + RATE_1M_INDEX, /* RATE_22M_INDEX - Not supported */ + RATE_1M_INDEX, /* RATE_33M_INDEX - Not supported */ + RATE_6M_INDEX, /* RATE_6M_INDEX */ + RATE_6M_INDEX, /* RATE_9M_INDEX */ + RATE_12M_INDEX, /* RATE_12M_INDEX */ + RATE_12M_INDEX, /* RATE_18M_INDEX */ + RATE_24M_INDEX, /* RATE_24M_INDEX */ + RATE_24M_INDEX, /* RATE_36M_INDEX */ + RATE_24M_INDEX, /* RATE_48M_INDEX */ + RATE_24M_INDEX /* RATE_54M_INDEX */ +}; + +const BOOLEAN afgIsOFDMRate[RATE_NUM] = { + FALSE, /* RATE_1M_INDEX = 0 */ + FALSE, /* RATE_2M_INDEX */ + FALSE, /* RATE_5_5M_INDEX */ + FALSE, /* RATE_11M_INDEX */ + FALSE, /* RATE_22M_INDEX - Not supported */ + FALSE, /* RATE_33M_INDEX - Not supported */ + TRUE, /* RATE_6M_INDEX */ + TRUE, /* RATE_9M_INDEX */ + TRUE, /* RATE_12M_INDEX */ + TRUE, /* RATE_18M_INDEX */ + TRUE, /* RATE_24M_INDEX */ + TRUE, /* RATE_36M_INDEX */ + TRUE, /* RATE_48M_INDEX */ + TRUE /* RATE_54M_INDEX */ +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Supported Rate & Extended Supported Rate IE to the +* Operational Rate Set and Basic Rate Set, and also check if any Basic +* Rate Code is unknown by driver. +* +* @param[in] prIeSupportedRate Pointer to the Supported Rate IE +* @param[in] prIeExtSupportedRate Pointer to the Ext Supported Rate IE +* @param[out] pu2OperationalRateSet Pointer to the Operational Rate Set +* @param[out] pu2BSSBasicRateSet Pointer to the Basic Rate Set +* @param[out] pfgIsUnknownBSSBasicRate Pointer to a Flag to indicate that Basic +* Rate Set has unknown Rate Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs ( + IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, + OUT PBOOLEAN pfgIsUnknownBSSBasicRate + ) +{ + UINT_16 u2OperationalRateSet = 0; + UINT_16 u2BSSBasicRateSet = 0; + BOOLEAN fgIsUnknownBSSBasicRate = FALSE; + UINT_8 ucRate; + UINT_32 i, j; + + + ASSERT(pu2OperationalRateSet); + ASSERT(pu2BSSBasicRateSet); + ASSERT(pfgIsUnknownBSSBasicRate); + + if (prIeSupportedRate) { + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + //ASSERT(prIeSupportedRate->ucLength <= ELEM_MAX_LEN_SUP_RATES); + ASSERT(prIeSupportedRate->ucLength <= RATE_NUM); + + for (i = 0; i < prIeSupportedRate->ucLength; i++) { + ucRate = prIeSupportedRate->aucSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate)/sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT) { + u2BSSBasicRateSet |= BIT(j); + } + + break; + } + } + + if ((j == sizeof(aucDataRate)/sizeof(UINT_8)) && + (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + + if (prIeExtSupportedRate) { + //ASSERT(prIeExtSupportedRate->ucLength <= ELEM_MAX_LEN_EXTENDED_SUP_RATES); + + for (i = 0; i < prIeExtSupportedRate->ucLength; i++) { + ucRate = prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate)/sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT) { + u2BSSBasicRateSet |= BIT(j); + } + + break; + } + } + + if ((j == sizeof(aucDataRate)/sizeof(UINT_8)) && + (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + *pu2OperationalRateSet = u2OperationalRateSet; + *pu2BSSBasicRateSet = u2BSSBasicRateSet; + *pfgIsUnknownBSSBasicRate = fgIsUnknownBSSBasicRate; + + return; + +} /* end of rateGetRateSetFromIEs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Operational Rate Set & Basic Rate Set to the Rate Code +* Format for used in (Ext)Supportec Rate IE. +* +* @param[in] u2OperationalRateSet Operational Rate Set +* @param[in] u2BSSBasicRateSet Basic Rate Set +* @param[out] pucDataRates Pointer to the Data Rate Buffer +* @param[out] pucDataRatesLen Pointer to the Data Rate Buffer Length +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetDataRatesFromRateSet ( + IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, + OUT PUINT_8 pucDataRates, + OUT PUINT_8 pucDataRatesLen + ) +{ + UINT_32 i, j; + + + ASSERT(pucDataRates); + ASSERT(pucDataRatesLen); + + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + for (i = RATE_1M_INDEX, j = 0; i < RATE_NUM; i++) { + if (u2OperationalRateSet & BIT(i)) { + + *(pucDataRates + j) = aucDataRate[i]; + + if (u2BSSBasicRateSet & BIT(i)) { + *(pucDataRates + j) |= RATE_BASIC_BIT; + } + + j++; + } + } + + *pucDataRatesLen = (UINT_8)j; + + return; + +} /* end of rateGetDataRatesFromRateSet() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the highest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucHighestRateIndex Pointer to buffer of the Highest Rate Index +* +* \retval TRUE Highest Rate Index was found +* \retval FALSE Highest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rateGetHighestRateIndexFromRateSet ( + IN UINT_16 u2RateSet, + OUT PUINT_8 pucHighestRateIndex + ) +{ + INT_32 i; + + + ASSERT(pucHighestRateIndex); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucHighestRateIndex = (UINT_8)i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetHighestRateIndexFromRateSet() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the lowest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucLowestRateIndex Pointer to buffer of the Lowest Rate Index +* +* \retval TRUE Lowest Rate Index was found +* \retval FALSE Lowest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rateGetLowestRateIndexFromRateSet ( + IN UINT_16 u2RateSet, + OUT PUINT_8 pucLowestRateIndex + ) +{ + UINT_32 i; + + ASSERT(pucLowestRateIndex); + + for (i = RATE_1M_INDEX; i <= RATE_54M_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (UINT_8)i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ + + +#if 0 // NOTE(Kevin): For reference +/*----------------------------------------------------------------------------*/ +/*! +* \brief Convert the given Data Rates to the Rate Set. +* +* \param[in] pucDataRates Pointer to the Data Rates +* \param[in] ucDataRatesLen Length of given Data Rates +* \param[out] pu2RateSet Pointer to the Rate Set +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromDataRates ( + IN PUINT_8 pucDataRates, + IN UINT_8 ucDataRatesLen, + OUT PUINT_16 pu2RateSet + ) +{ + UINT_16 u2RateSet = 0; + UINT_8 ucRate; + UINT_32 i, j; + + + ASSERT(pucDataRates); + ASSERT(pu2RateSet); + + if (pucDataRates) { + for (i = 0; i < ucDataRatesLen; i++) { + ucRate = pucDataRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate)/sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2RateSet |= BIT(j); + break; + } + } + } + } + + *pu2RateSet = u2RateSet; + + return; + +} /* end of rateGetRateSetFromDataRates() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the Operational Rate Set and Basic Rate Set to get the corresponding +* ACK/CTS(Respnose) TX Rates. +* +* \param[in] u2OperationalRateSet Operational Rate Set +* \param[in] u2BSSBasicRateSet Basic Rate Set +* \param[out] aucAckCtsRateIndex Pointer to the Ack/Cts Data Rate Buffer +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateSetAckCtsDataRatesFromRateSet ( + IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, + IN OUT UINT_8 aucAckCtsRateIndex[] + ) +{ + INT_32 i,j; + + + ASSERT(aucAckCtsRateIndex); + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + /* Setup default ACK/CTS response rate */ + kalMemCopy(aucAckCtsRateIndex, (PVOID)aucDefaultAckCtsRateIndex, sizeof(aucDefaultAckCtsRateIndex)); + + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2OperationalRateSet & BIT(i)) { + for (j = i; j >= RATE_1M_INDEX; j--) { + if (u2BSSBasicRateSet & BIT(j)) { + if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) // Reply ACK Frame at the same Modulation Scheme. + aucAckCtsRateIndex[i] = (UINT_8)j; + break; + } + } + + /* NOTE(Kevin 2008/03/25): Following code is used for those AP which has + * NULL BasicRateSet. + * e.g. If input Operational Rate Set = [18M 12M 9M], Basic Rate Set = NULL. + * Originally we'll get Ack Rate for [18M 12M 9M] is [12M 12M "6M"]. + * Now we'll get Ack Rate for [18M 12M 9M] is [12M 12M 9M], + * The Ack Rate for Tx Rates which are not list in Operational Rate Set is still + * use highest mandatory rate as default. + */ + if (j < RATE_1M_INDEX) { /* The ACK/CTS rate was not found in BasicRateSet */ + if (!(BIT(aucAckCtsRateIndex[i]) & u2OperationalRateSet)) { + aucAckCtsRateIndex[i] = (UINT_8)i; + } + } + } + } + + return; + +} /* end of rateSetAckCtsDataRatesFromRateSet() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the proper initial rate from Rate Set according to given RCPI value +* +* \param[in] u2RateSet Rate Set +* \param[in] rRcpi RCPI value from AP or Peer STA +* \param[out] pucInitialRateIndex Pointer to buffer of the initial Rate Index +* +* \retval TRUE Initial Rate Index was found +* \retval FALSE Initial Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rateGetBestInitialRateIndex ( + IN UINT_16 u2RateSet, + IN RCPI rRcpi, + OUT PUINT_8 pucInitialRateIndex + ) +{ + UINT_16 u2InitRateSet; + INT_32 i; + + + ASSERT(pucInitialRateIndex); + + DBGLOG(MGT, TRACE, ("rRcpi = %d\n", rRcpi)); + + if (rRcpi >= RCPI_100) { /* Best Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_100); + } + else if (rRcpi >= RCPI_80) { /* Better Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_80); + } + else if (rRcpi >= RCPI_60) { /* Good Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_60); + } + else { /* Worse Signal */ + /* NOTE(Kevin): If return FALSE, we should assign the BSS Basic Rate Index + * (prBssInfo->ucBasicRateIndex) to the initial rate. It was determined in + * function - bssUpdateTxRateForControlFrame(). + */ + return FALSE; + } + + u2RateSet &= u2InitRateSet; + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucInitialRateIndex = (UINT_8)i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetBestInitialRateIndex() */ +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c new file mode 100755 index 000000000000..1954f88e48dd --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c @@ -0,0 +1,1723 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#2 $ +*/ + +/*! \file "rlm.c" + \brief + +*/ + + + +/* +** $Log: rlm.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Check length HT cap IE about RX associate request frame + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 03 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Fix preamble type of STA mode + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Not send ERP IE if peer STA is 802.11b-only + * + * 10 11 2011 cm.chang + * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter + * Ignore HT OP IE if its length field is not valid + * + * 09 28 2011 cm.chang + * NULL + * Add length check to reduce possibility to adopt wrong IE + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Handle client mode about preamble type and slot time + * + * 09 01 2011 cm.chang + * [WCXRP00000971] [MT6620 Wi-Fi][Driver][FW] Not set Beacon timeout interval when CPTT + * Final channel number only adopts the field from assoc response + * + * 06 10 2011 cm.chang + * [WCXRP00000773] [MT6620 Wi-Fi][Driver] Workaround some AP fill primary channel field with its secondary channel + * If DS IE exists, ignore the primary channel field in HT OP IE + * + * 05 03 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Fix compiling error + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Refine range of valid channel number + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Check if channel is valided before record ing BSS channel + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 15 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when no mgmt buffer in free build + * + * 10 08 2010 cm.chang + * NULL + * When 20M only setting, ignore OBSS IE + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 23 2010 chinghwa.yu + * NULL + * Temporary add rlmUpdateParamByStaForBow() and rlmBssInitForBow(). + * + * 08 23 2010 chinghwa.yu + * NULL + * Add CFG_ENABLE_BT_OVER_WIFI. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Fix compile error while enabling WiFi Direct function. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix channel ID definition in RFB status to primary channel instead of center channel + * + * 06 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add TX short GI compiling option + * + * 06 02 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Roll back to remove CFG_SUPPORT_BCM_TEST. + * + * 06 01 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Update BCM Test and RW configuration. + * + * 05 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some compiling options to control 11n functions + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set RTS threshold of 2K bytes initially + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Utilize status of swRfb to know channel number and band + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 04 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process Beacon only ready for infra STA now + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 24 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * fixed some WHQL testing error. + * + * 03 15 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide draft measurement and quiet functions + * + * 03 09 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * If bss is not 11n network, zero WTBL HT parameters + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 03 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Generate HT IE only depending on own phyTypeSet + * + * 03 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not fill HT related IE if BssInfo does not include 11n phySet + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * To store field AMPDU Parameters in STA_REC + * + * 02 26 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable RDG RX, but disable RDG TX for IOT and LongNAV + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Modify the parameter of rlmRecAssocRspHtInfo function + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix prBssInfo->ucPrimaryChannel handle for assoc resp + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add some function to process HT operation + * + * Nov 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call rlmStatisticsInit() to handle MIB counters + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID +rlmFillHtCapIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ); + +static VOID +rlmFillExtCapIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ); + +static VOID +rlmFillHtOpIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ); + +static UINT_8 +rlmRecIeInfoForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +static BOOLEAN +rlmRecBcnFromNeighborForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +static BOOLEAN +rlmRecBcnInfoForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ); + +static VOID +rlmBssReset ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFsmEventInit ( + P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + /* Note: assume TIMER_T structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFsmEventUninit ( + P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucNetIdx; + + ASSERT(prAdapter); + + RLM_NET_FOR_EACH(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + /* Note: all RLM timers will also be stopped. + * Now only one OBSS scan timer. + */ + rlmBssReset(prAdapter, prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmReqGenerateHtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) { + + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmReqGenerateExtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) { + + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmRspGenerateHtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (RLM_NET_IS_11N(prBssInfo) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) { + + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmRspGenerateExtCapIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (RLM_NET_IS_11N(prBssInfo) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) { + + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmRspGenerateHtOpIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11N(prBssInfo) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) { + + rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmRspGenerateErpIE ( + P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + P_IE_ERP_T prErpIe; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11GN))) { + prErpIe = (P_IE_ERP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add ERP IE */ + prErpIe->ucId = ELEM_ID_ERP_INFO; + prErpIe->ucLength = 1; + + prErpIe->ucERP = prBssInfo->fgObssErpProtectMode ? + ERP_INFO_USE_PROTECTION : 0; + + if (prBssInfo->fgErpProtectMode) { + prErpIe->ucERP |= + (ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION); + } + + /* Handle barker preamble */ + if (!prBssInfo->fgUseShortPreamble) { + prErpIe->ucERP |= ERP_INFO_BARKER_PREAMBLE_MODE; + } + + ASSERT(IE_SIZE(prErpIe) <= (ELEM_HDR_LEN+ ELEM_MAX_LEN_ERP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prErpIe); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmFillHtCapIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_IE_HT_CAP_T prHtCap; + P_SUP_MCS_SET_FIELD prSupMcsSet; + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (P_IE_HT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled) { + prHtCap->u2HtCapInfo &= + ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + } + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) { + prSupMcsSet->aucRxMcsBitmask[32/8] = BIT(0); /* MCS32 */ + } + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + prHtCap->u2HtExtendedCap &= + ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + } + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmFillExtCapIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_EXT_CAP_T prExtCap; + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + /* Add Extended Capabilities IE */ + prExtCap = (P_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + prExtCap->ucLength = 1; + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) { + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + } + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + } + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmFillHtOpIE ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo + ) +{ + P_IE_HT_OP_T prHtOp; + UINT_16 i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prHtOp = (P_IE_HT_OP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; + + /* RIFS and 20/40 bandwidth operations are included */ + prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; + + /* Decide HT protection mode field */ + if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) { + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; + } + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; + } + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; + } + + if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { + /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED + * Note: it will also be set in ad-hoc network + */ + prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (0 /* Regulatory class 16 */ && + prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection + * although it is possible to have no protection by spec. + */ + prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ + + /* No basic MCSx are needed temporarily */ + for (i = 0; i < 16; i++) { + prHtOp->aucBasicMcsSet[i] = 0; + } + + ASSERT(IE_SIZE(prHtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtOp); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked to update parameters of associated AP. +* (Association response and Beacon) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 +rlmRecIeInfoForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + UINT_16 u2Offset; + P_STA_RECORD_T prStaRec; + P_IE_HT_CAP_T prHtCap; + P_IE_HT_OP_T prHtOp; + P_IE_OBSS_SCAN_PARAM_T prObssScnParam; + UINT_8 ucERP, ucPrimaryChannel; +#if CFG_SUPPORT_QUIET && 0 + BOOLEAN fgHasQuietIE = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + if (!prStaRec) { + return 0; + } + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are vaild only when the corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) { + break; + } + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32/8] & BIT(0)) ? + TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + case ELEM_ID_HT_OP: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) { + break; + } + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPrimaryChannel == 0) { + ucPrimaryChannel = prHtOp->ucPrimaryChannel; + } + prBssInfo->ucHtOpInfo1 = prHtOp->ucInfo1; + prBssInfo->u2HtOpInfo2 = prHtOp->u2Info2; + prBssInfo->u2HtOpInfo3 = prHtOp->u2Info3; + + if (!prBssInfo->fg40mBwAllowed) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + } + + if ((prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + prBssInfo->eBssSCO = (ENUM_CHNL_EXT_T) + (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO); + } + + prBssInfo->eHtProtectMode = (ENUM_HT_PROTECT_MODE_T) + (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_HT_PROTECTION); + + /* To do: process regulatory class 16 */ + if ((prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) + && 0 /* && regulatory class is 16 */) { + prBssInfo->eGfOperationMode = GF_MODE_DISALLOWED; + } + else if (prBssInfo->u2HtOpInfo2&HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { + prBssInfo->eGfOperationMode = GF_MODE_PROTECT; + } + else { + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + } + + prBssInfo->eRifsOperationMode = + (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_RIFS_MODE) ? + RIFS_MODE_NORMAL : RIFS_MODE_DISALLOWED; + + break; + + case ELEM_ID_20_40_BSS_COEXISTENCE: + if (!RLM_NET_IS_11N(prBssInfo)) { + break; + } + /* To do: store if scanning exemption grant to BssInfo */ + break; + + case ELEM_ID_OBSS_SCAN_PARAMS: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) { + break; + } + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; + break; + + case ELEM_ID_EXTENDED_CAP: + if (!RLM_NET_IS_11N(prBssInfo)) { + break; + } + /* To do: store extended capability (PSMP, coexist) to BssInfo */ + break; + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || + prBssInfo->eBand != BAND_2G4) { + break; + } + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = + (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) { + prBssInfo->fgUseShortPreamble = FALSE; + } + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) { + ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + } + break; + + #if CFG_SUPPORT_QUIET && 0 + /* Note: RRM code should be moved to independent RRM function by + * component design rule. But we attach it to RLM temporarily + */ + case ELEM_ID_QUIET: + rrmQuietHandleQuietIE(prBssInfo, (P_IE_QUIET_T) pucIE); + fgHasQuietIE = TRUE; + break; + #endif + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + /* Some AP will have wrong channel number (255) when running time. + * Check if correct channel number information. 20110501 + */ + if ((prBssInfo->eBand == BAND_2G4 && ucPrimaryChannel > 14) || + (prBssInfo->eBand != BAND_2G4 && (ucPrimaryChannel >= 200 || + ucPrimaryChannel <= 14))) { + ucPrimaryChannel = 0; + } + +#if CFG_SUPPORT_QUIET && 0 + if (!fgHasQuietIE) { + rrmQuietIeNotExist(prAdapter, prBssInfo); + } +#endif + + /* Check if OBSS scan process will launch */ + if (!prAdapter->fgEnOnlineScan || !prObssScnParam || + !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH) || + prBssInfo->eBand != BAND_2G4 || !prBssInfo->fg40mBwAllowed) { + + /* Note: it is ok not to stop rObssScanTimer() here */ + prBssInfo->u2ObssScanInterval = 0; + } + else { + if (prObssScnParam->u2TriggerScanInterval < OBSS_SCAN_MIN_INTERVAL) { + prObssScnParam->u2TriggerScanInterval = OBSS_SCAN_MIN_INTERVAL; + } + if (prBssInfo->u2ObssScanInterval != + prObssScnParam->u2TriggerScanInterval) { + + prBssInfo->u2ObssScanInterval = + prObssScnParam->u2TriggerScanInterval; + + /* Start timer to trigger OBSS scanning */ + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } + } + + return ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnFromNeighborForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + UINT_16 u2Offset, i; + UINT_8 ucPriChannel, ucSecChannel; + ENUM_CHNL_EXT_T eSCO; + BOOLEAN fgHtBss, fg20mReq; + + ASSERT(prAdapter); + ASSERT(prBssInfo && prSwRfb); + ASSERT(pucIE); + + /* Record it to channel list to change 20/40 bandwidth */ + ucPriChannel = 0; + eSCO = CHNL_EXT_SCN; + + fgHtBss = FALSE; + fg20mReq = FALSE; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + { + P_IE_HT_CAP_T prHtCap; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) { + break; + } + + prHtCap = (P_IE_HT_CAP_T) pucIE; + if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) { + fg20mReq = TRUE; + } + fgHtBss = TRUE; + break; + } + case ELEM_ID_HT_OP: + { + P_IE_HT_OP_T prHtOp; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) { + break; + } + + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPriChannel == 0) { + ucPriChannel = prHtOp->ucPrimaryChannel; + } + + if ((prHtOp->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + eSCO = (ENUM_CHNL_EXT_T) (prHtOp->ucInfo1 & HT_OP_INFO1_SCO); + } + break; + } + case ELEM_ID_20_40_BSS_COEXISTENCE: + { + P_IE_20_40_COEXIST_T prCoexist; + + if (IE_LEN(pucIE) != (sizeof(IE_20_40_COEXIST_T) - 2)) { + break; + } + + prCoexist = (P_IE_20_40_COEXIST_T) pucIE; + if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) { + fg20mReq = TRUE; + } + break; + } + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) != (sizeof(IE_DS_PARAM_SET_T) - 2)) { + break; + } + ucPriChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + + default: + break; + } + } + + + /* To do: Update channel list and 5G band. All channel lists have the same + * update procedure. We should give it the entry pointer of desired + * channel list. + */ + if (HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr) != BAND_2G4) { + return FALSE; + } + + if (ucPriChannel == 0 || ucPriChannel > 14) { + ucPriChannel = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + } + + if (fgHtBss) { + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_PriChnlList[i] == ucPriChannel) { + break; + } + } + if ((i > prBssInfo->auc2G_PriChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_PriChnlList[i] = ucPriChannel; + prBssInfo->auc2G_PriChnlList[0]++; + } + + /* Update secondary channel */ + if (eSCO != CHNL_EXT_SCN) { + ucSecChannel = (eSCO == CHNL_EXT_SCA) ? + (ucPriChannel + 4) : (ucPriChannel - 4); + + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_SecChnlList[i] == ucSecChannel) { + break; + } + } + if ((i > prBssInfo->auc2G_SecChnlList[0])&& (i <= CHNL_LIST_SZ_2G)){ + prBssInfo->auc2G_SecChnlList[i] = ucSecChannel; + prBssInfo->auc2G_SecChnlList[0]++; + } + } + + /* Update 20M bandwidth request channels */ + if (fg20mReq) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == ucPriChannel) { + break; + } + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && + (i <= CHNL_LIST_SZ_2G)){ + prBssInfo->auc2G_20mReqChnlList[i] = ucPriChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + } + else { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && + i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == ucPriChannel) { + break; + } + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = ucPriChannel; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + + } + + return FALSE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnInfoForClient ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo && prSwRfb); + ASSERT(pucIE); + +#if 0 /* SW migration 2010/8/20 */ + /* Note: we shall not update parameters when scanning, otherwise + * channel and bandwidth will not be correct or asserted failure + * during scanning. + * Note: remove channel checking. All received Beacons should be processed + * if measurement or other actions are executed in adjacent channels + * and Beacon content checking mechanism is not disabled. + */ + if (IS_SCAN_ACTIVE() + /* || prBssInfo->ucPrimaryChannel != CHNL_NUM_BY_SWRFB(prSwRfb) */) { + return FALSE; + } +#endif + + /* Handle change of slot time */ + prBssInfo->u2CapInfo = + ((P_WLAN_BEACON_FRAME_T)(prSwRfb->pvHeader))->u2CapInfo; + prBssInfo->fgUseShortSlotTime = + (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmProcessBcn ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgNewParameter; + UINT_8 ucNetIdx; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be procesed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + RLM_NET_FOR_EACH_NO_BOW(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* P2P client or AIS infra STA */ + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, + ((P_WLAN_MAC_MGMT_HEADER_T) + (prSwRfb->pvHeader))->aucBSSID)) { + + fgNewParameter = rlmRecBcnInfoForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, u2IELength); + } + else { + fgNewParameter = rlmRecBcnFromNeighborForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, u2IELength); + } + } + #if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE)) { + /* AP scan to check if 20/40M bandwidth is permitted */ + rlmRecBcnFromNeighborForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, u2IELength); + } + #endif + else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } /* end of RLM_NET_FOR_EACH_NO_BOW */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmProcessAssocRsp ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPriChannel; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) { + return; + } + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prStaRec == prBssInfo->prStaRecOfAP); + + /* To do: the invoked function is used to clear all members. It may be + * done by center mechanism in invoker. + */ + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fgUseShortSlotTime = + (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + if ((ucPriChannel = + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength)) > 0) { + prBssInfo->ucPrimaryChannel = ucPriChannel; + } + + if (!RLM_NET_IS_11N(prBssInfo) || + !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) { + prBssInfo->fg40mBwAllowed = FALSE; + } + + /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), which + * shall be invoked afterwards. + * Update channel, bandwidth and protection mode by nicUpdateBss() + */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFillSyncCmdParam ( + P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, + P_BSS_INFO_T prBssInfo + ) +{ + ASSERT(prCmdBody && prBssInfo); + if (!prCmdBody || !prBssInfo) { + return; + } + + prCmdBody->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prCmdBody->ucRfBand = (UINT_8) prBssInfo->eBand; + prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prBssInfo->eBssSCO; + prCmdBody->ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; + prCmdBody->ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; + prCmdBody->ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; + prCmdBody->ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; + prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + prCmdBody->ucCheckId = 0x72; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + DBGLOG(RLM, INFO, ("N=%d b=%d c=%d s=%d e=%d h=%d I=0x%02x l=%d p=%d\n", + prCmdBody->ucNetTypeIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble)); + } + else { + DBGLOG(RLM, INFO, ("N=%d closed\n", prCmdBody->ucNetTypeIndex)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will operation parameters based on situations of +* concurrent networks. Channel, bandwidth, protection mode, supported +* rate will be modified. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmSyncOperationParams ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + P_CMD_SET_BSS_RLM_PARAM_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prCmdBody = (P_CMD_SET_BSS_RLM_PARAM_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_BSS_RLM_PARAM_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(RLM, WARN, ("No buf for sync RLM params (Net=%d)\n", + prBssInfo->ucNetTypeIndex)); + return; + } + + rlmFillSyncCmdParam(prCmdBody, prBssInfo); + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_SET_BSS_RLM_PARAM, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_BSS_RLM_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); +} + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmProcessAssocReq ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb, + PUINT_8 pucIE, + UINT_16 u2IELength + ) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + P_IE_HT_CAP_T prHtCap; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) { + return; + } + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) { + break; + } + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32/8] & BIT(0)) ? + TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ +} +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmBssInitForAPandIbss ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + rlmBssInitForAP(prAdapter, prBssInfo); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmBssAborted ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + /* Assume FW state is updated by CMD_ID_SET_BSS_INFO, so + * the sync CMD is not needed here. + */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief All RLM timers will also be stopped. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmBssReset ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + /* HT related parameters */ + prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ + prBssInfo->u2HtOpInfo2 = 0; + prBssInfo->u2HtOpInfo3 = 0; + + prBssInfo->eBssSCO = 0; + prBssInfo->fgErpProtectMode = 0; + prBssInfo->eHtProtectMode = 0; + prBssInfo->eGfOperationMode = 0; + prBssInfo->eRifsOperationMode = 0; + + /* OBSS related parameters */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + /* All RLM timers will also be stopped */ + cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); + prBssInfo->u2ObssScanInterval = 0; + + prBssInfo->fgObssErpProtectMode = 0; /* GO only */ + prBssInfo->eObssHtProtectMode = 0; /* GO only */ + prBssInfo->eObssGfOperationMode = 0; /* GO only */ + prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ + prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ + prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c new file mode 100755 index 000000000000..b5f34388469b --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c @@ -0,0 +1,681 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#1 $ +*/ + +/*! \file "rlm_domain.c" + \brief + +*/ + + + +/* +** $Log: rlm_domain.c $ + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 09 23 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Let channel number to zero if band is illegal + * + * 09 22 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Exclude channel list with illegal band + * + * 09 15 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use defined country group to have a change to add new group + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Provide legal channel function based on domain + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 02 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Export rlmDomainGetDomainInfo for p2p driver. + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 03 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Filter out not supported RF freq when reporting available chnl list + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide query function about full channle list. + * + * Dec 1 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* The following country or domain shall be set from host driver. + * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as + * the channel list of being a STA to do scanning/searching AP or being an + * AP to choose an adequate channel if auto-channel is set. + */ + +/* Define mapping tables between country code and its channel set + */ +static const UINT_16 g_u2CountryGroup0[] = +{ + COUNTRY_CODE_US, COUNTRY_CODE_BS, COUNTRY_CODE_BB, COUNTRY_CODE_BO, COUNTRY_CODE_DM, + COUNTRY_CODE_DO, COUNTRY_CODE_HT, COUNTRY_CODE_PR, COUNTRY_CODE_TH, COUNTRY_CODE_TW, + COUNTRY_CODE_AI, COUNTRY_CODE_AG, COUNTRY_CODE_AW, COUNTRY_CODE_BM, COUNTRY_CODE_CU, + COUNTRY_CODE_GD, COUNTRY_CODE_GY, COUNTRY_CODE_JM, COUNTRY_CODE_KN, COUNTRY_CODE_LC, + COUNTRY_CODE_VC, COUNTRY_CODE_TT, COUNTRY_CODE_SR +}; +static const UINT_16 g_u2CountryGroup1[] = +{ + COUNTRY_CODE_BR, COUNTRY_CODE_EC, COUNTRY_CODE_HK, COUNTRY_CODE_MX, COUNTRY_CODE_PE, + COUNTRY_CODE_CR, COUNTRY_CODE_MD, COUNTRY_CODE_NI, COUNTRY_CODE_PZ +}; +static const UINT_16 g_u2CountryGroup2[] = {COUNTRY_CODE_CO, COUNTRY_CODE_PY}; +static const UINT_16 g_u2CountryGroup3[] = {COUNTRY_CODE_JP}; +static const UINT_16 g_u2CountryGroup4[] = +{ + COUNTRY_CODE_CN, COUNTRY_CODE_UY, COUNTRY_CODE_MA +}; +static const UINT_16 g_u2CountryGroup5[] = {COUNTRY_CODE_AR}; +static const UINT_16 g_u2CountryGroup6[] = {COUNTRY_CODE_AU, COUNTRY_CODE_NZ}; +static const UINT_16 g_u2CountryGroup7[] = {COUNTRY_CODE_RU}; +static const UINT_16 g_u2CountryGroup8[] = +{ + COUNTRY_CODE_ID, COUNTRY_CODE_HN, COUNTRY_CODE_PG, COUNTRY_CODE_PK +}; +static const UINT_16 g_u2CountryGroup9[] = {COUNTRY_CODE_CA}; +static const UINT_16 g_u2CountryGroup10[] = +{ + COUNTRY_CODE_CL, COUNTRY_CODE_IN, COUNTRY_CODE_SA, COUNTRY_CODE_SG, COUNTRY_CODE_VE, + COUNTRY_CODE_MY, COUNTRY_CODE_VN, COUNTRY_CODE_EG +}; +static const UINT_16 g_u2CountryGroup11[] = {COUNTRY_CODE_IL, COUNTRY_CODE_UA}; +static const UINT_16 g_u2CountryGroup12[] = {COUNTRY_CODE_JO, COUNTRY_CODE_KW}; +static const UINT_16 g_u2CountryGroup13[] = {COUNTRY_CODE_KR, COUNTRY_CODE_OM}; +static const UINT_16 g_u2CountryGroup14[] = +{ + COUNTRY_CODE_EU + /* When country code is not found, this domain info will be used. + * So mark all country codes to reduce search time. 20110908 + */ + /*, COUNTRY_CODE_PH, COUNTRY_CODE_TR, COUNTRY_CODE_IR, COUNTRY_CODE_BY, + COUNTRY_CODE_LK */ +}; + + +DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE }, /* CH_SET_2G4_1_11 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_UPPER_NA */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_14 */ + { 82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE }, + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_NULL, 0, 0, 0, FALSE } /* CH_SET_UNII_UPPER_NA */ + } + }, + { + (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_LOW_NA */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_LOW_NA */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_WW_NA */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE }, /* CH_SET_2G4_1_11 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE }, /* CH_SET_UNII_UPPER_149_161 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE }, /* CH_SET_UNII_UPPER_149_161 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_LOW_NA */ + { 118, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_MID_NA */ + { 121, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_WW_NA */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE }, /* CH_SET_UNII_UPPER_149_161 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE }, /* CH_SET_2G4_1_11 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 5, FALSE }, /* CH_SET_UNII_WW_100_116_132_140 */ + { 121, BAND_5G, CHNL_SPAN_20, 132, 5, FALSE }, + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + } + }, + { + (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_WW_NA */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_WW_NA */ + { 125, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_UPPER_NA */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_MID_NA */ + { 121, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_WW_NA */ + { 125, BAND_NULL, 0, 0, 0, FALSE }, /* CH_SET_UNII_UPPER_NA */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + (PUINT_16) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 8, FALSE }, /* CH_SET_UNII_WW_100_128 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE }, /* CH_SET_UNII_UPPER_149_165 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + }, + { + /* Note: The final one is for Europe union now. */ + (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, + { + { 81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE }, /* CH_SET_2G4_1_13 */ + + { 115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE }, /* CH_SET_UNII_LOW_36_48 */ + { 118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE }, /* CH_SET_UNII_MID_52_64 */ + { 121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE }, /* CH_SET_UNII_WW_100_140 */ + { 125, BAND_5G, CHNL_SPAN_20, 149, 7, FALSE }, /* CH_SET_UNII_UPPER_149_173 */ + { 0, BAND_NULL, 0, 0, 0, FALSE } + } + } +}; + +#if 0 +COUNTRY_CH_SET_T arCountryChSets[] = { + /* idx=0: US, Bahamas, Barbados, Bolivia(Voluntary), Dominica (the Commonwealth of Dominica), + The Dominican Republic, Haiti */ + {CH_SET_2G4_1_11, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_165}, + /* idx=1: Brazil, Ecuador, Hong Kong, Mexico, Peru */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_165}, + /* idx=2: JP1, Colombia(Voluntary), Paraguay */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_NA}, + /* idx=3: JP2 */ + {CH_SET_2G4_1_14, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_NA}, + /* idx=4: CN, Uruguay, Morocco */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_NA, CH_SET_UNII_MID_NA, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_149_165}, + /* idx=5: Argentina */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_NA, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_149_165}, + /* idx=6: Australia, New Zealand */ + {CH_SET_2G4_1_11, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_161}, + /* idx=7: Russia */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_161}, + /* idx=8: Indonesia */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_NA, CH_SET_UNII_MID_NA, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_149_161}, + /* idx=9: Canada */ + {CH_SET_2G4_1_11, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_116_132_140, CH_SET_UNII_UPPER_149_165}, + /* idx=10: Chile, India, Saudi Arabia, Singapore */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_149_165}, + /* idx=11: Israel, Ukraine */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_NA}, + /* idx=12: Jordan, Kuwait */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_NA, + CH_SET_UNII_WW_NA, CH_SET_UNII_UPPER_NA}, + /* idx=13: South Korea */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_128, CH_SET_UNII_UPPER_149_165}, + /* idx=14: Taiwan */ + {CH_SET_2G4_1_11, CH_SET_UNII_LOW_NA, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_165}, + /* idx=15: EU all countries */ + {CH_SET_2G4_1_13, CH_SET_UNII_LOW_36_48, CH_SET_UNII_MID_52_64, + CH_SET_UNII_WW_100_140, CH_SET_UNII_UPPER_149_173} +}; +#endif + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_DOMAIN_INFO_ENTRY +rlmDomainGetDomainInfo ( + P_ADAPTER_T prAdapter + ) +{ +#define REG_DOMAIN_DEF_IDX 14 /* EU (Europe Union) */ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) + + UINT_16 i, j; + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_REG_INFO_T prRegInfo; + UINT_16 u2TargetCountryCode; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) { + return prAdapter->prDomainInfo; + } + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, INFO, ("Domain: map=%d, idx=%d, code=0x%04x\n", + prRegInfo->eRegChannelListMap, prRegInfo->ucRegChannelListIndex, + prAdapter->rWifiVar.rConnSettings.u2CountryCode)); + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; + goto L_set_domain_info; + } + else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + prDomainInfo = &prRegInfo->rDomainInfo; + goto L_set_domain_info; + } + + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + /* If no matched country code, the final one will be used + * The final one is for Europe union now. + */ + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + ASSERT((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0); + + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) { + break; + } + } + if (j < prDomainInfo->u4CountryNum) { + break; /* Found */ + } + } + + DATA_STRUC_INSPECTING_ASSERT(REG_DOMAIN_DEF_IDX < REG_DOMAIN_GROUP_NUM); + + if (i >= REG_DOMAIN_GROUP_NUM) { + prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; + } + +L_set_domain_info: + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] The input variable pointed by pucNumOfChannel is the max +* arrary size. The return value indciates meaning list size. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmDomainGetChnlList ( + P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, + UINT_8 ucMaxChannelNum, + PUINT_8 pucNumOfChannel, + P_RF_CHANNEL_INFO_T paucChannelList + ) +{ + UINT_8 i, j, ucNum; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + /* If no matched country code, the final one will be used */ + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_NULL || prSubband->ucBand >= BAND_NUM || + (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand)) { + continue; + } + + if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) { + break; + } + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmDomainSendCmd ( + P_ADAPTER_T prAdapter, + BOOLEAN fgIsOid + ) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + WLAN_STATUS rStatus; + UINT_8 i; + P_DOMAIN_SUBBAND_INFO prSubBand; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + ASSERT(prCmd); + + /* To do: exception handle */ + if (!prCmd) { + DBGLOG(RLM, ERROR, ("Domain: no buf to send cmd\n")); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2Reserved = 0; + prCmd->uc2G4Bandwidth = + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + + for (i = 0; i < 6; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Update domain info to chip */ + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return TRUE Legal channel +* FALSE Illegal channel for current regulatory domain +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainIsLegalChannel ( + P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, + UINT_8 ucChannel + ) +{ + UINT_8 i, j; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) { + continue; + } + + if (prSubband->ucBand == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j*prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c new file mode 100755 index 000000000000..143d72104a24 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c @@ -0,0 +1,461 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 $ +*/ + +/*! \file "rlm_obss.c" + \brief + +*/ + + + +/* +** $Log: rlm_obss.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Avoid possible OBSS scan when BSS is switched + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Regulation class is changed to 81 in 20_40_coexistence action frame + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 13 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Use SCO of BSS_INFO to replace user-defined setting variables + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 26 2010 yuche.tsai + * + * Fix compile error while enabling WiFi Direct function. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add more ASSERT to check exception + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID +rlmObssScanTimeout ( + P_ADAPTER_T prAdapter, + UINT_32 u4Data + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmObssInit ( + P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucNetIdx; + + RLM_NET_FOR_EACH(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, + rlmObssScanTimeout, (UINT_32) prBssInfo); + } /* end of RLM_NET_FOR_EACH */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmObssUpdateChnlLists ( + P_ADAPTER_T prAdapter, + P_SW_RFB_T prSwRfb + ) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmObssScanDone ( + P_ADAPTER_T prAdapter, + P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + UINT_16 i, u2PayloadLen; + + ASSERT(prMsgHdr); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prScanDoneMsg->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, ("OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucNetTypeIndex, prBssInfo->eCurrentOPMode)); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + return; + } +#endif + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, ("OBSS Scan Done (NetIdx=%d) -- Aborted!!\n", + prBssInfo->ucNetTypeIndex)); + return; + } + + /* To do: check 2.4G channel list to decide if obss mgmt should be + * sent to associated AP. Note: how to handle concurrent network? + * To do: invoke rlmObssChnlLevel() to decide if 20/40 BSS coexistence + * management frame is needed. + */ + if ((prBssInfo->auc2G_20mReqChnlList[0] > 0 || + prBssInfo->auc2G_NonHtChnlList[0] > 0) && + (prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN)) != NULL) { + + DBGLOG(RLM, INFO, ("Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], + prBssInfo->auc2G_NonHtChnlList[0])); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) + ((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = + (prBssInfo->auc2G_20mReqChnlList[0] > 0) ? BSS_COEXIST_20M_REQ : 0; + + u2PayloadLen = 2 + 3; + + if (prBssInfo->auc2G_NonHtChnlList[0] > 0) { + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + + prTxFrame->rChnlReport.ucId = ELEM_ID_20_40_INTOLERANT_CHNL_REPORT; + prTxFrame->rChnlReport.ucLength = + prBssInfo->auc2G_NonHtChnlList[0] + 1; + prTxFrame->rChnlReport.ucRegulatoryClass = 81; /* 2.4GHz, ch1~13 */ + for (i = 0; i < prBssInfo->auc2G_NonHtChnlList[0] && + i < CHNL_LIST_SZ_2G; i++) { + prTxFrame->rChnlReport.aucChannelList[i] = + prBssInfo->auc2G_NonHtChnlList[i+1]; + } + + u2PayloadLen += IE_SIZE(&prTxFrame->rChnlReport); + } + ASSERT((WLAN_MAC_HEADER_LEN + u2PayloadLen) <= PUBLIC_ACTION_MAX_LEN); + + /* Clear up channel lists in 2.4G band */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + + + //4 Update information of MSDU_INFO_T + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + //4 Enqueue the frame to send this action frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + } /* end of prMsduInfo != NULL */ + + if (prBssInfo->u2ObssScanInterval > 0) { + DBGLOG(RLM, INFO, ("Set OBSS timer (NetIdx=%d, %d sec)\n", + prBssInfo->ucNetTypeIndex, prBssInfo->u2ObssScanInterval)); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmObssScanTimeout ( + P_ADAPTER_T prAdapter, + UINT_32 u4Data + ) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = (P_BSS_INFO_T) u4Data; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if (prAdapter->fgIsP2PRegistered && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, ("OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", + prBssInfo->ucNetTypeIndex)); + return; + } + + rlmObssTriggerScan(prAdapter, prBssInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmObssTriggerScan ( + P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo + ) +{ + P_MSG_SCN_SCAN_REQ prScanReqMsg; + + ASSERT(prBssInfo); + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + ASSERT(prScanReqMsg); + + if (!prScanReqMsg) { + DBGLOG(RLM, WARN, ("No buf for OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucNetTypeIndex)); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + return; + } + + /* It is ok that ucSeqNum is set to fixed value because the same network + * OBSS scan interval is limited to OBSS_SCAN_MIN_INTERVAL (min 10 sec) + * and scan module don't care seqNum of OBSS scanning + */ + prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = 0x33; + prScanReqMsg->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDLength = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + prScanReqMsg->u2IELen = 0; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prScanReqMsg, + MSG_SEND_METHOD_BUF); + + DBGLOG(RLM, INFO, ("Timeout to trigger OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucNetTypeIndex)); +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c new file mode 100755 index 000000000000..27ffda023bf8 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c @@ -0,0 +1,108 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_protection.c#1 $ +*/ + +/*! \file "rlm_protection.c" + \brief + +*/ + + + +/* +** $Log: rlm_protection.c $ + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set RTS threshold of 2K bytes initially + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 03 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable RTS threshold temporarily for AMPDU + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c new file mode 100755 index 000000000000..c941873eb8f3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c @@ -0,0 +1,583 @@ +/* +** $Id: +*/ + +/*! \file "roaming_fsm.c" + \brief This file defines the FSM for Roaming MODULE. + + This file defines the FSM for Roaming MODULE. +*/ + + + +/* +** $Log: roaming_fsm.c $ + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_ROAMING +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugRoamingState[ROAMING_STATE_NUM] = { + (PUINT_8)DISP_STRING("ROAMING_STATE_IDLE"), + (PUINT_8)DISP_STRING("ROAMING_STATE_DECISION"), + (PUINT_8)DISP_STRING("ROAMING_STATE_DISCOVERY"), + (PUINT_8)DISP_STRING("ROAMING_STATE_ROAM") +}; +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define ROAMING_ENABLE_CHECK(_roam) \ + { \ + if (!(_roam->fgIsEnableRoaming)) {return;} \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmInit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DBGLOG(ROAMING, LOUD, ("->roamingFsmInit(): Current Time = %ld\n", kalGetTimeTick())); + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + //4 <1> Initiate FSM + prRoamingFsmInfo->fgIsEnableRoaming = prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; + + return; +} /* end of roamingFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the value in AIS_FSM_INFO_T for AIS FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmUninit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, ("->roamingFsmUninit(): Current Time = %ld\n", kalGetTimeTick())); + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + + return; +} /* end of roamingFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send commands to firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmSendCmd ( + IN P_ADAPTER_T prAdapter, + IN P_ROAMING_PARAM_T prParam + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + WLAN_STATUS rStatus; + + DBGLOG(ROAMING, LOUD, ("->roamingFsmSendCmd(): Current Time = %ld\n", kalGetTimeTick())); + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_ROAMING_TRANSIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(ROAMING_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prParam, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return; +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the recent time when ScanDone occurred +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmScanResultsUpdate ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + DBGLOG(ROAMING, LOUD, ("->roamingFsmScanResultsUpdate(): Current Time = %ld\n", kalGetTimeTick())); + + GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); + + return; +} /* end of roamingFsmScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of ROAMING for AIS Infra. +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN ENUM_ROAMING_STATE_T] eNextState Enum value of next AIS STATE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN ENUM_ROAMING_STATE_T eNextState + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T ePreviousState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + do { + + /* Do entering Next State */ +#if DBG + DBGLOG(ROAMING, STATE, ("TRANSITION: [%s] -> [%s]\n", + apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], + apucDebugRoamingState[eNextState])); +#else + DBGLOG(ROAMING, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n", + DBG_ROAMING_IDX, + prRoamingFsmInfo->eCurrentState, + eNextState)); +#endif + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + ePreviousState = prRoamingFsmInfo->eCurrentState; + prRoamingFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN)FALSE; + + /* Do tasks of the State that we just entered */ + switch (prRoamingFsmInfo->eCurrentState) { + /* NOTE(Kevin): we don't have to rearrange the sequence of following + * switch case. Instead I would like to use a common lookup table of array + * of function pointer to speed up state search. + */ + case ROAMING_STATE_IDLE: + case ROAMING_STATE_DECISION: + break; + + case ROAMING_STATE_DISCOVERY: + { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC))) { + DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Timeout")); + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + } + else { + DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Updated")); + aisFsmRunEventRoamingDiscovery(prAdapter, FALSE); + } + } + break; + + case ROAMING_STATE_ROAM: + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + } + } + while (fgIsTransition); + + return; + +} /* end of roamingFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state after join completion +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmRunEventStart ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + return; + } + + DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING START: Current Time = %ld\n", kalGetTimeTick())); + + /* IDLE, ROAM -> DECISION */ + /* Errors as DECISION, DISCOVERY -> DECISION */ + if (!(prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE + || prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) { + return; + } + + eNextState = ROAMING_STATE_DECISION; + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_START; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) &rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of roamingFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Discovery state when deciding to find a candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmRunEventDiscovery ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING DISCOVERY: Current Time = %ld\n", kalGetTimeTick())); + + /* DECISION -> DISCOVERY */ + /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DECISION) { + return; + } + + eNextState = ROAMING_STATE_DISCOVERY; + /* DECISION -> DISCOVERY */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + + // sync. rcpi with firmware + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc) { + prBssDesc->ucRCPI = (UINT_8)(u4Param&0xff); + } + + roamingFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Roam state after Scan Done +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmRunEventRoam ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING ROAM: Current Time = %ld\n", kalGetTimeTick())); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, ROAM -> ROAM */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DISCOVERY) { + return; + } + + eNextState = ROAMING_STATE_ROAM; + /* DISCOVERY -> ROAM */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ROAM; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) &rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of roamingFsmRunEventRoam() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state as being failed to find out any candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmRunEventFail ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Param + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING FAIL: reason %x Current Time = %ld\n", u4Param, kalGetTimeTick())); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, DISCOVERY -> DECISION */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_ROAM) { + return; + } + + eNextState = ROAMING_STATE_DECISION; + /* ROAM -> DECISION */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_FAIL; + rParam.u2Data = (UINT_16)(u4Param&0xffff); + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) &rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of roamingFsmRunEventFail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Idle state as beging aborted by other moduels, AIS +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +roamingFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); + + ROAMING_ENABLE_CHECK(prRoamingFsmInfo); + + DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING ABORT: Current Time = %ld\n", kalGetTimeTick())); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ABORT; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) &rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + + return; +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process events from firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +roamingFsmProcessEvent ( + IN P_ADAPTER_T prAdapter, + IN P_ROAMING_PARAM_T prParam + ) +{ + DBGLOG(ROAMING, LOUD, ("ROAMING Process Events: Current Time = %ld\n", kalGetTimeTick())); + + if (ROAMING_EVENT_DISCOVERY == prParam->u2Event) { + roamingFsmRunEventDiscovery(prAdapter, prParam->u2Data); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c new file mode 100755 index 000000000000..a576b1d2a222 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c @@ -0,0 +1,2671 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rsn.c#2 $ +*/ + +/*! \file "rsn.c" + \brief This file including the 802.11i, wpa and wpa2(rsn) related function. + + This file provided the macros and functions library support the wpa/rsn ie parsing, + cipher and AKM check to help the AP seleced deciding, tkip mic error handler and rsn PMKID support. +*/ + + + +/* +** $Log: rsn.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 09 2012 chinglan.wang + * NULL + * Fix the condition error. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 12 24 2010 chinglan.wang + * NULL + * [MT6620][Wi-Fi] Modify the key management in the driver for WPS function. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 11 03 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Refine the HT rate disallow TKIP pairwise cipher . + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 29 2010 yuche.tsai + * NULL + * Fix compile error, remove unused pointer in rsnGenerateRSNIE(). + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 08 30 2010 wh.su + * NULL + * remove non-used code. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * [WPD00003840] [MT6620 5931] Security migration + * migration from firmware. + * + * 05 27 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * not indiate pmkid candidate while no new one scaned. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the name + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * using the Rx0 port to indicate event + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine the code for generate the WPA/RSN IE for assoc req + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust code for pmkid event + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code for event (mic error and pmkid indicate) and do some function rename + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security function + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security feature, including pmkid + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_RSN_MIGRATION + +//extern PHY_ATTRIBUTE_T rPhyAttributes[]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse RSN IE. +* +* \param[in] prInfoElem Pointer to the RSN IE +* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the +** RSN information from the given RSN IE +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnParseRsnIE ( + IN P_ADAPTER_T prAdapter, + IN P_RSN_INFO_ELEM_T prInfoElem, + OUT P_RSN_INFO_T prRsnInfo + ) +{ + UINT_32 i; + INT_32 u4RemainRsnIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUINT_8 pucPairSuite = NULL; + PUINT_8 pucAuthSuite = NULL; + PUINT_8 cp; + + DEBUGFUNC("rsnParseRsnIE"); + + ASSERT(prInfoElem); + ASSERT(prRsnInfo); + + /* Verify the length of the RSN IE. */ + if (prInfoElem->ucLength < 2) { + DBGLOG(RSN, TRACE, ("RSN IE length too short (length=%d)\n", prInfoElem->ucLength)); + return FALSE; + } + + /* Check RSN version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(RSN, TRACE,("Unsupported RSN IE version: %d\n", u2Version)); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainRsnIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainRsnIeLen == 0) { + break; + } + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, TRACE, ("Fail to parse RSN IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainRsnIeLen -= 4; + + if (u4RemainRsnIeLen == 0) { + break; + } + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE,("Fail to parse RSN IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE,("Fail to parse RSN IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (INT_32) i; + + if (u4RemainRsnIeLen == 0) { + break; + } + + /* Parse the Authentication and Key Management Cipher Suite Count field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE,("Fail to parse RSN IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, ("Fail to parse RSN IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (INT_32) i; + + if (u4RemainRsnIeLen == 0) { + break; + } + + /* Parse the RSN u2Capabilities field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, ("Fail to parse RSN IE in RSN capabilities (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + } while (FALSE); + + /* Save the RSN information for the BSS. */ + prRsnInfo->ucElemId = ELEM_ID_RSN; + + prRsnInfo->u2Version = u2Version; + + prRsnInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, LOUD, ("RSN: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF))); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) { + u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; + } + + prRsnInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prRsnInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, ("RSN: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for RSN: CCMP. */ + prRsnInfo->u4PairwiseKeyCipherSuiteCount = 1; + prRsnInfo->au4PairwiseKeyCipherSuite[0] = RSN_CIPHER_SUITE_CCMP; + + DBGLOG(RSN, LOUD, ("RSN: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF))); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) { + u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; + } + + prRsnInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prRsnInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, ("RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for RSN. */ + prRsnInfo->u4AuthKeyMgtSuiteCount = 1; + prRsnInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; + + DBGLOG(RSN, LOUD, ("RSN: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF))); + } + + prRsnInfo->u2RsnCap = u2Cap; +#if CFG_SUPPORT_802_11W + prRsnInfo->fgRsnCapPresent = TRUE; +#endif + DBGLOG(RSN, LOUD, ("RSN cap: 0x%04x\n", prRsnInfo->u2RsnCap)); + + return TRUE; +} /* rsnParseRsnIE */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse WPA IE. +* +* \param[in] prInfoElem Pointer to the WPA IE. +* \param[out] prWpaInfo Pointer to the BSSDescription structure to store the +* WPA information from the given WPA IE. +* +* \retval TRUE Succeeded. +* \retval FALSE Failed. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnParseWpaIE ( + IN P_ADAPTER_T prAdapter, + IN P_WPA_INFO_ELEM_T prInfoElem, + OUT P_RSN_INFO_T prWpaInfo + ) +{ + UINT_32 i; + INT_32 u4RemainWpaIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = WPA_CIPHER_SUITE_TKIP; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUCHAR pucPairSuite = NULL; + PUCHAR pucAuthSuite = NULL; + PUCHAR cp; + BOOLEAN fgCapPresent = FALSE; + + DEBUGFUNC("rsnParseWpaIE"); + + ASSERT(prInfoElem); + ASSERT(prWpaInfo); + + /* Verify the length of the WPA IE. */ + if (prInfoElem->ucLength < 6) { + DBGLOG(RSN, TRACE,("WPA IE length too short (length=%d)\n", prInfoElem->ucLength)); + return FALSE; + } + + /* Check WPA version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(RSN, TRACE, ("Unsupported WPA IE version: %d\n", u2Version)); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainWpaIeLen = (INT_32) prInfoElem->ucLength - 6; + + do { + if (u4RemainWpaIeLen == 0) { + break; + } + + /* WPA_OUI : 4 + Version : 2 + GroupSuite : 4 + PairwiseCount: 2 + PairwiseSuite: 4 * pairSuiteCount + AuthCount : 2 + AuthSuite : 4 * authSuiteCount + Cap : 2 */ + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWpaIeLen < 4) { + DBGLOG(RSN, TRACE,("Fail to parse WPA IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWpaIeLen -= 4; + + if (u4RemainWpaIeLen == 0) { + break; + } + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE,("Fail to parse WPA IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWpaIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWpaIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE,("Fail to parse WPA IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWpaIeLen -= (INT_32) i; + + if (u4RemainWpaIeLen == 0) { + break; + } + + /* Parse the Authentication and Key Management Cipher Suite Count + field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE,("Fail to parse WPA IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWpaIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWpaIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, ("Fail to parse WPA IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWpaIeLen -= (INT_32) i; + + if (u4RemainWpaIeLen == 0) { + break; + } + + /* Parse the WPA u2Capabilities field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE, ("Fail to parse WPA IE in WPA capabilities (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + fgCapPresent = TRUE; + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWpaIeLen -= 2; + } while (FALSE); + + /* Save the WPA information for the BSS. */ + + prWpaInfo->ucElemId = ELEM_ID_WPA; + + prWpaInfo->u2Version = u2Version; + + prWpaInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, LOUD, ("WPA: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF))); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) { + u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; + } + + prWpaInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prWpaInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, ("WPA: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for WPA: TKIP. */ + prWpaInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWpaInfo->au4PairwiseKeyCipherSuite[0] = WPA_CIPHER_SUITE_TKIP; + + DBGLOG(RSN, LOUD, ("WPA: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF))); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) { + u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; + } + + prWpaInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWpaInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, ("WPA: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for WPA. */ + prWpaInfo->u4AuthKeyMgtSuiteCount = 1; + prWpaInfo->au4AuthKeyMgtSuite[0] = WPA_AKM_SUITE_802_1X; + + DBGLOG(RSN, LOUD, ("WPA: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF))); + } + + if (fgCapPresent) { + prWpaInfo->fgRsnCapPresent = TRUE; + prWpaInfo->u2RsnCap = u2Cap; + DBGLOG(RSN, LOUD, ("WPA: RSN cap: 0x%04x\n", prWpaInfo->u2RsnCap)); + } + else { + prWpaInfo->fgRsnCapPresent = FALSE; + prWpaInfo->u2RsnCap = 0; + } + + return TRUE; +} /* rsnParseWpaIE */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the desired pairwise +* cipher suite from the MIB Pairwise Cipher Suite +* configuration table. +* +* \param[in] u4Cipher The desired pairwise cipher suite to be searched +* \param[out] pu4Index Pointer to the index of the desired pairwise cipher in +* the table +* +* \retval TRUE - The desired pairwise cipher suite is found in the table. +* \retval FALSE - The desired pairwise cipher suite is not found in the +* table. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnSearchSupportedCipher ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Cipher, + OUT PUINT_32 pu4Index + ) +{ + UINT_8 i; + P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; + + DEBUGFUNC("rsnSearchSupportedCipher"); + + ASSERT(pu4Index); + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i]; + if (prEntry->dot11RSNAConfigPairwiseCipher == u4Cipher && + prEntry->dot11RSNAConfigPairwiseCipherEnabled) { + *pu4Index = i; + return TRUE; + } + } + return FALSE; +} /* rsnSearchSupportedCipher */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether BSS RSN is matched from upper layer set. +* +* \param[in] prAdapter Pointer to the Adapter structure, BSS RSN Information +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnIsSuitableBSS ( + IN P_ADAPTER_T prAdapter, + IN P_RSN_INFO_T prBssRsnInfo + ) +{ + UINT_8 i = 0; + + DEBUGFUNC("rsnIsSuitableBSS"); + + do{ + + if((prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite & 0x000000FF) != \ + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite)){ + DBGLOG(RSN, TRACE, ("Break by GroupKeyCipherSuite\n")); + break; + } + for(i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++){ + if(((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] & 0x000000FF) != \ + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i])) + && (i == prBssRsnInfo->u4PairwiseKeyCipherSuiteCount - 1) ){ + DBGLOG(RSN, TRACE, ("Break by PairwiseKeyCipherSuite\n")); + break; + } + } + for(i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++){ + if(((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] & 0x000000FF) != \ + GET_SELECTOR_TYPE(prBssRsnInfo->au4AuthKeyMgtSuite[0])) + && (i == prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1)){ + DBGLOG(RSN, TRACE, ("Break by AuthKeyMgtSuite \n")); + break; + } + } + return TRUE; + }while(FALSE); + return FALSE; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to search the desired +* authentication and key management (AKM) suite from the +* MIB Authentication and Key Management Suites table. +* +* \param[in] u4AkmSuite The desired AKM suite to be searched +* \param[out] pu4Index Pointer to the index of the desired AKM suite in the +* table +* +* \retval TRUE The desired AKM suite is found in the table. +* \retval FALSE The desired AKM suite is not found in the table. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnSearchAKMSuite ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4AkmSuite, + OUT PUINT_32 pu4Index + ) +{ + UINT_8 i; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + + DEBUGFUNC("rsnSearchAKMSuite"); + + ASSERT(pu4Index); + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite && + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled) { + *pu4Index = i; + return TRUE; + } + } + return FALSE; +} /* rsnSearchAKMSuite */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform RSNA or TSN policy +* selection for a given BSS. +* +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The RSNA/TSN policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The RSNA/TSN policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnPerformPolicySelection ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ) +{ +#if CFG_SUPPORT_802_11W + INT_32 i; + UINT_32 j; +#else + UINT_32 i, j; +#endif + BOOLEAN fgSuiteSupported; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_RSN_INFO_T prBssRsnInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetwotkType; + BOOLEAN fgIsWpsActive = (BOOLEAN)FALSE; + + DEBUGFUNC("rsnPerformPolicySelection"); + + ASSERT(prBss); + + DBGLOG(RSN, TRACE, ("rsnPerformPolicySelection\n")); + //Todo:: + eNetwotkType = NETWORK_TYPE_AIS_INDEX; + + prBss->u4RsnSelectedPairwiseCipher = 0; + prBss->u4RsnSelectedGroupCipher = 0; + prBss->u4RsnSelectedAKMSuite = 0; + prBss->ucEncLevel = 0; + +#if CFG_SUPPORT_WPS + fgIsWpsActive = kalWSCGetActiveState(prAdapter->prGlueInfo); + + /* CR1640, disable the AP select privacy check */ + if ( fgIsWpsActive && + (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) && + (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA)) { + DBGLOG(RSN, TRACE,("-- Skip the Protected BSS check\n")); + return TRUE; + } +#endif + + /* Protection is not required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) == 0 ) { + + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, TRACE,("-- No Protected BSS\n")); + return TRUE; + } + else { + DBGLOG(RSN, TRACE,("-- Protected BSS\n")); + return FALSE; + } + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, TRACE,("-- Protected BSS\n")); + return FALSE; + } + } + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + + if (prBss->fgIEWPA) { + prBssRsnInfo = &prBss->rWPAInfo; + } + else { + DBGLOG(RSN, TRACE, ("WPA Information Element does not exist.\n")); + return FALSE; + } + } + else if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2 || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK) { + + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } + else { + DBGLOG(RSN, TRACE, ("RSN Information Element does not exist.\n")); + return FALSE; + } + } + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, ignore this BSS. */ + DBGLOG(RSN, TRACE, ("-- Not WEP-only legacy BSS\n")); + return FALSE; + } + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, use this BSS. */ + DBGLOG(RSN, TRACE, ("-- WEP-only legacy BSS\n")); + return TRUE; + } + + if(!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) + { + DBGLOG(RSN, TRACE, ("RSN info check no matched\n")); + return FALSE; + } + + if (prBssRsnInfo->u4PairwiseKeyCipherSuiteCount == 1 && + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[0]) == + CIPHER_SUITE_NONE) { + /* Since the pairwise cipher use the same cipher suite as the group + cipher in the BSS, we check the group cipher suite against the + current encryption status. */ + fgSuiteSupported = FALSE; + + switch (prBssRsnInfo->u4GroupKeyCipherSuite) { + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_ENABLED) { + fgSuiteSupported = TRUE; + } + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION2_ENABLED) { + fgSuiteSupported = TRUE; + } + break; + + case WPA_CIPHER_SUITE_WEP40: + case WPA_CIPHER_SUITE_WEP104: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION1_ENABLED) { + fgSuiteSupported = TRUE; + } + break; + } + + if (fgSuiteSupported) { + u4PairwiseCipher = WPA_CIPHER_SUITE_NONE; + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } +#if DBG + else { + DBGLOG(RSN, TRACE, ("Inproper encryption status %d for group-key-only BSS\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus)); + } +#endif + } + else { + fgSuiteSupported = FALSE; + + DBGLOG(RSN, TRACE, ("eEncStatus %d %d 0x%x\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + prBssRsnInfo->au4PairwiseKeyCipherSuite[0])); + /* Select pairwise/group ciphers */ + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) + { + case ENUM_ENCRYPTION3_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_CCMP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION2_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_TKIP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == + CIPHER_SUITE_CCMP) { + DBGLOG(RSN, TRACE, ("Cannot join CCMP BSS\n")); + } + else { + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + case ENUM_ENCRYPTION1_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP104) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == + CIPHER_SUITE_CCMP || + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == + CIPHER_SUITE_TKIP) { + DBGLOG(RSN, TRACE, ("Cannot join CCMP/TKIP BSS\n")); + } + else { + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + default: + break; + } + } + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + BSS, do not check the supported AKM suites. */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(RSN, TRACE, ("Failed to select pairwise/group cipher (0x%08lx/0x%08lx)\n", + u4PairwiseCipher, u4GroupCipher)); + return FALSE; + } + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (eNetwotkType == NETWORK_TYPE_P2P_INDEX)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || + u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, TRACE, ("Failed to select pairwise/group cipher for P2P network (0x%08lx/0x%08lx)\n", + u4PairwiseCipher, u4GroupCipher)); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (eNetwotkType == NETWORK_TYPE_BOW_INDEX) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || + u4AkmSuite != RSN_AKM_SUITE_PSK) { + } + DBGLOG(RSN, TRACE, ("Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08lx/0x%08lx)\n", + u4PairwiseCipher, u4GroupCipher)); + return FALSE; + } +#endif + + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4PairwiseCipher, &i); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) { + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4GroupCipher, &i); + } + + if (!fgSuiteSupported) { + DBGLOG(RSN, TRACE, ("Failed to support selected pairwise/group cipher (0x%08lx/0x%08lx)\n", + u4PairwiseCipher, u4GroupCipher)); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + the given BSS, we fail to perform RSNA policy selection. */ + /* Attempt to find any overlapping supported AKM suite. */ +#if CFG_SUPPORT_802_11W + if (i != 0) + for (i = (prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1); i >= 0; i--) +#else + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) +#endif + { + if (rsnSearchAKMSuite(prAdapter, + prBssRsnInfo->au4AuthKeyMgtSuite[i], + &j)) { + u4AkmSuite = prBssRsnInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(RSN, TRACE, ("Cannot support any AKM suites\n")); + return FALSE; + } + + DBGLOG(RSN, TRACE, ("Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF))); + + DBGLOG(RSN, TRACE, ("Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF))); + +#if CFG_SUPPORT_802_11W + DBGLOG(RSN, TRACE, ("MFP setting = %d\n ", kalGetMfpSetting(prAdapter->prGlueInfo))); + + if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + if (!prBssRsnInfo->fgRsnCapPresent) { + DBGLOG(RSN, TRACE, ("Skip RSN IE, No MFP Required Capability.\n")); + return FALSE; + } + else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { + DBGLOG(RSN, TRACE, ("Skip RSN IE, No MFP Required\n")); + return FALSE; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + } + else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { + if (prBssRsnInfo->u2RsnCap && ((prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR) || + (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC))) { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + } + else { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + } + } + else { + if (prBssRsnInfo->fgRsnCapPresent && (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { + DBGLOG(RSN, TRACE, ("Skip RSN IE, No MFP Required Capability\n")); + return FALSE; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + } + DBGLOG(RSN, TRACE, ("fgMgmtProtection = %d\n ", prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection)); +#endif + + if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP){ + prBss->ucEncLevel = 3; + } + else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_TKIP){ + prBss->ucEncLevel = 2; + } + else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP104) { + prBss->ucEncLevel = 1; + } + else { + ASSERT(FALSE); + } + prBss->u4RsnSelectedPairwiseCipher = u4PairwiseCipher; + prBss->u4RsnSelectedGroupCipher = u4GroupCipher; + prBss->u4RsnSelectedAKMSuite = u4AkmSuite; + + return TRUE; + +} /* rsnPerformPolicySelection */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate WPA IE for beacon frame. +* +* \param[in] pucIeStartAddr Pointer to put the generated WPA IE. +* +* \return The append WPA-None IE length +* \note +* Called by: JOIN module, compose beacon IE +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGenerateWpaNoneIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + UINT_32 i; + P_WPA_INFO_ELEM_T prWpaIE; + UINT_32 u4Suite; + UINT_16 u2SuiteCount; + PUINT_8 cp, cp2; + UINT_8 ucExpendedLen = 0; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) { + return; + } + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T)prMsduInfo->ucNetworkType; + + if (eNetworkId != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + prWpaIE = (P_WPA_INFO_ELEM_T)(pucBuffer); + + /* Start to construct a WPA IE. */ + /* Fill the Element ID field. */ + prWpaIE->ucElemId = ELEM_ID_WPA; + + /* Fill the OUI and OUI Type fields. */ + prWpaIE->aucOui[0] = 0x00; + prWpaIE->aucOui[1] = 0x50; + prWpaIE->aucOui[2] = 0xF2; + prWpaIE->ucOuiType = VENDOR_OUI_TYPE_WPA; + + /* Fill the Version field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2Version, 1); /* version 1 */ + ucExpendedLen = 6; + + /* Fill the Pairwise Key Cipher Suite List field. */ + u2SuiteCount = 0; + cp = (PUINT_8)&prWpaIE->aucPairwiseKeyCipherSuite1[0]; + + if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) { + u4Suite = WPA_CIPHER_SUITE_CCMP; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) { + u4Suite = WPA_CIPHER_SUITE_TKIP; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) { + u4Suite = WPA_CIPHER_SUITE_WEP104; + } + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) { + u4Suite = WPA_CIPHER_SUITE_WEP40; + } + else { + u4Suite = WPA_CIPHER_SUITE_TKIP; + } + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Group Key Cipher Suite field as the same in pair-wise key. */ + WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); + ucExpendedLen += 4; + + /* Fill the Pairwise Key Cipher Suite Count field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, u2SuiteCount); + ucExpendedLen += 2; + + cp2 = cp; + + /* Fill the Authentication and Key Management Suite List field. */ + u2SuiteCount = 0; + cp += 2; + + if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) { + u4Suite = WPA_AKM_SUITE_802_1X; + } + else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) { + u4Suite = WPA_AKM_SUITE_PSK; + } + else { + u4Suite = WPA_AKM_SUITE_NONE; + } + + /* This shall be the only avaiable value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (UINT_8)ucExpendedLen; + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +} /* rsnGenerateWpaNoneIE */ + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGenerateWPAIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + PUCHAR cp; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + + DEBUGFUNC("rsnGenerateWPAIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T)prMsduInfo->ucNetworkType; + + //if (eNetworkId != NETWORK_TYPE_AIS_INDEX) + // return; + +#if CFG_ENABLE_WIFI_DIRECT + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->fgIsP2PRegistered) && + (eNetworkId == NETWORK_TYPE_P2P_INDEX) && + (kalP2PGetTkipCipher(prAdapter->prGlueInfo)))) || + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK))) +#else + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK)))) +#endif + { + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) + { + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, WPA_CIPHER_SUITE_TKIP); + } + else +#endif + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedGroupCipher); + + cp = (PUCHAR) &WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) + { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } + else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedPairwiseCipher); + cp += 4; + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) + { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } + else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedAKMSuite); + cp += 4; + + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* rsnGenerateWPAIE */ + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate RSN IE for +* associate request frame. +* +* \param[in] prMsduInfo The Selected BSS description +* +* \retval The append RSN IE length +* +* \note +* Called by: AIS module, P2P module, BOW module Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGenerateRSNIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + UINT_32 u4Entry; + PUCHAR cp; + //UINT_8 ucExpendedLen = 0; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("rsnGenerateRSNIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* Todo:: network id */ + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T)prMsduInfo->ucNetworkType; + + if ( +#if CFG_ENABLE_WIFI_DIRECT + ((prAdapter->fgIsP2PRegistered) && + (eNetworkId == NETWORK_TYPE_P2P_INDEX) && + (kalP2PGetCcmpCipher(prAdapter->prGlueInfo))) || +#endif +#if CFG_ENABLE_BT_OVER_WIFI + (eNetworkId == NETWORK_TYPE_BOW_INDEX) || +#endif + (eNetworkId == NETWORK_TYPE_AIS_INDEX /* prCurrentBss->fgIERSN */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK)))) + { + /* Construct a RSN IE for association request frame. */ + RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; + RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); // Version + WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedGroupCipher); // Group key suite + cp = (PUCHAR) &RSN_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedPairwiseCipher); + cp += 4; + WLAN_SET_FIELD_16(cp, 1); // AKM suite count + cp += 2; + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedAKMSuite); // AKM suite + cp += 4; + WLAN_SET_FIELD_16(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u2RsnSelectedCapInfo); // Capabilities +#if CFG_SUPPORT_802_11W + if (eNetworkId == NETWORK_TYPE_AIS_INDEX && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection) { + if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); // Capabilities + } + else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); // Capabilities + } + } +#endif + cp += 2; + + if (eNetworkId == NETWORK_TYPE_AIS_INDEX) + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (eNetworkId == NETWORK_TYPE_AIS_INDEX && + rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry)) { + //DBGLOG(RSN, TRACE, ("Add Pmk at assoc req\n")); + //DBGLOG(RSN, TRACE, ("addr " MACSTR" PMKID "MACSTR"\n", + // MAC2STR(prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arBSSID), MAC2STR(prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arPMKID))); + if (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist) { + RSN_IE(pucBuffer)->ucLength = 38; + WLAN_SET_FIELD_16(cp, 1); // PMKID count + cp += 2; + DBGLOG(RSN, TRACE, ("BSSID "MACSTR" ind=%d\n", MAC2STR(prStaRec->aucMacAddr), u4Entry)); + DBGLOG(RSN, TRACE, ("use PMKID "MACSTR"\n", MAC2STR(prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arPMKID))); + kalMemCopy(cp, (PVOID)prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arPMKID, + sizeof(PARAM_PMKID_VALUE)); + //ucExpendedLen = 40; + } + else { + WLAN_SET_FIELD_16(cp, 0); // PMKID count + //ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; +#if CFG_SUPPORT_802_11W + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; +#endif + } + } + else { + WLAN_SET_FIELD_16(cp, 0); // PMKID count + //ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; +#if CFG_SUPPORT_802_11W + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; +#endif + } + +#if CFG_SUPPORT_802_11W + if ((eNetworkId == NETWORK_TYPE_AIS_INDEX) && (kalGetMfpSetting(prAdapter->prGlueInfo) != RSN_AUTH_MFP_DISABLED) /* (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) */ ) { + WLAN_SET_FIELD_32(cp, RSN_CIPHER_SUITE_AES_128_CMAC); + cp += 4; + RSN_IE(pucBuffer)->ucLength += 4; + } +#endif + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* rsnGenerateRSNIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the given IE buffer and check if it is WFA IE and return Type and +* SubType for further process. +* +* \param[in] pucBuf Pointer to the buffer of WFA Information Element. +* \param[out] pucOuiType Pointer to the storage of OUI Type. +* \param[out] pu2SubTypeVersion Pointer to the storage of OUI SubType and Version. + +* \retval TRUE Parse IE ok +* \retval FALSE Parse IE fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnParseCheckForWFAInfoElem ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, + OUT PUINT_8 pucOuiType, + OUT PUINT_16 pu2SubTypeVersion + ) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_IE_WFA_T prWfaIE; + + ASSERT(pucBuf); + ASSERT(pucOuiType); + ASSERT(pu2SubTypeVersion); + prWfaIE = (P_IE_WFA_T)pucBuf; + + do { + if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { + break; + } + else if (prWfaIE->aucOui[0] != aucWfaOui[0] || + prWfaIE->aucOui[1] != aucWfaOui[1] || + prWfaIE->aucOui[2] != aucWfaOui[2]) { + break; + } + + *pucOuiType = prWfaIE->ucOuiType; + WLAN_GET_FIELD_16(&prWfaIE->aucOuiSubTypeVersion[0], pu2SubTypeVersion); + + return TRUE; + } + while (FALSE); + + return FALSE; + +} /* end of rsnParseCheckForWFAInfoElem() */ + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the given IE buffer and check if it is RSN IE with CCMP PSK +* +* \param[in] prAdapter Pointer to Adapter +* \param[in] prSwRfb Pointer to the rx buffer +* \param[in] pIE Pointer rthe buffer of Information Element. +* \param[out] prStatusCode Pointer to the return status code. + +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void +rsnParserCheckForRSNCCMPPSK( + P_ADAPTER_T prAdapter, + P_RSN_INFO_ELEM_T prIe, + PUINT_16 pu2StatusCode + ) +{ + + RSN_INFO_T rRsnIe; + + ASSERT(prAdapter); + ASSERT(prIe); + ASSERT(pu2StatusCode); + + *pu2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; + + if (rsnParseRsnIE(prAdapter, prIe, &rRsnIe)) { + if ((rRsnIe.u4PairwiseKeyCipherSuiteCount != 1) || (rRsnIe.au4PairwiseKeyCipherSuite[0] != RSN_CIPHER_SUITE_CCMP)) { + *pu2StatusCode = STATUS_CODE_INVALID_PAIRWISE_CIPHER; + return; + } + if ((rRsnIe.u4GroupKeyCipherSuite != RSN_CIPHER_SUITE_CCMP)) { + *pu2StatusCode = STATUS_CODE_INVALID_GROUP_CIPHER; + return; + } + if ((rRsnIe.u4AuthKeyMgtSuiteCount != 1) || (rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_PSK)) { + *pu2StatusCode = STATUS_CODE_INVALID_AKMP; + return; + } + + DBGLOG(RSN, TRACE, ("RSN with CCMP-PSK\n" )); + *pu2StatusCode = WLAN_STATUS_SUCCESS; + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate an authentication event to NDIS. +* +* \param[in] u4Flags Authentication event: \n +* PARAM_AUTH_REQUEST_REAUTH 0x01 \n +* PARAM_AUTH_REQUEST_KEYUPDATE 0x02 \n +* PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 \n +* PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E \n +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGenMicErrorEvent ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgFlags + ) +{ + P_PARAM_AUTH_EVENT_T prAuthEvent; + + DEBUGFUNC("rsnGenMicErrorEvent"); + + prAuthEvent = (P_PARAM_AUTH_EVENT_T)prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID)prAuthEvent->arRequest[0].arBssid, (PVOID)prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID, MAC_ADDR_LEN); + + if (fgFlags == TRUE) + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); + +} /* rsnGenMicErrorEvent */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle TKIP MIC failures. +* +* \param[in] adapter_p Pointer to the adapter object data area. +* \param[in] prSta Pointer to the STA which occur MIC Error +* \param[in] fgErrorKeyType type of error key +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnTkipHandleMICFailure ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + IN BOOLEAN fgErrorKeyType + ) +{ + //UINT_32 u4RsnaCurrentMICFailTime; + //P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnTkipHandleMICFailure"); + + ASSERT(prAdapter); +#if 1 + rsnGenMicErrorEvent(prAdapter,/* prSta,*/ fgErrorKeyType); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, ("Generate TKIP MIC error event (type: 0%d)\n", + fgErrorKeyType)); +#else + ASSERT(prSta); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Record the MIC error occur time. */ + GET_CURRENT_SYSTIME(&u4RsnaCurrentMICFailTime); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, ("Generate TKIP MIC error event (type: 0%d)\n", + fgErrorKeyType)); + + /* If less than 60 seconds have passed since a previous TKIP MIC failure, + disassociate from the AP and wait for 60 seconds before (re)associating + with the same AP. */ + if (prAisSpecBssInfo->u4RsnaLastMICFailTime != 0 && + !CHECK_FOR_TIMEOUT(u4RsnaCurrentMICFailTime, + prAisSpecBssInfo->u4RsnaLastMICFailTime, + SEC_TO_SYSTIME(TKIP_COUNTERMEASURE_SEC))) { + /* If less than 60 seconds expired since last MIC error, we have to + block traffic. */ + + DBGLOG(RSN, INFO, ("Start blocking traffic!\n")); + rsnGenMicErrorEvent( prAdapter,/* prSta,*/ fgErrorKeyType); + + secFsmEventStartCounterMeasure(prAdapter, prSta); + } + else { + rsnGenMicErrorEvent( prAdapter,/* prSta,*/ fgErrorKeyType); + DBGLOG(RSN, INFO, ("First TKIP MIC error!\n")); + } + + COPY_SYSTIME(prAisSpecBssInfo->u4RsnaLastMICFailTime, u4RsnaCurrentMICFailTime); +#endif +} /* rsnTkipHandleMICFailure */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS Desc at scan result list +* \param[out] pu4CandidateCount Pointer to the number of selected candidates. +* It is set to zero if no BSSID matches our requirement. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnSelectPmkidCandidateList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("rsnSelectPmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + /* Search a BSS with the same SSID from the given BSS description set. */ + //DBGLOG(RSN, TRACE, ("Check scan result ["MACSTR"]\n", + // MAC2STR(prBssDesc->aucBSSID))); + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, ("-- SSID not matched\n")); + return; + } + +#if 0 + if ((prBssDesc->u2BSSBasicRateSet & + ~(rPhyAttributes[prAisBssInfo->ePhyType].u2SupportedRateSet)) || + prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(RSN, TRACE, ("-- Rate set not matched\n")); + return; + } + + if (/* prBssDesc->u4RsnSelectedPairwiseCipher != prAisBssInfo->u4RsnSelectedPairwiseCipher ||*/ + prBssDesc->u4RsnSelectedGroupCipher != prAisBssInfo->u4RsnSelectedGroupCipher /*|| + prBssDesc->u4RsnSelectedAKMSuite != prAisBssInfo->u4RsnSelectedAKMSuite */) { + DBGLOG(RSN, TRACE, ("-- Encrypt status not matched for PMKID \n")); + return; + } +#endif + + rsnUpdatePmkidCandidateList(prAdapter, prBssDesc); + +} /* rsnSelectPmkidCandidateList */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS DESC at scan result list +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnUpdatePmkidCandidateList ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc + ) +{ + UINT_32 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnUpdatePmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, ("-- SSID not matched\n")); + return; + } + + for (i = 0; i < CFG_MAX_PMKID_CACHE; i++) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)) + return; + } + + /* If the number of selected BSSID exceed MAX_NUM_PMKID_CACHE(16), + then we only store MAX_NUM_PMKID_CACHE(16) in PMKID cache */ + if ((prAisSpecBssInfo->u4PmkidCandicateCount + 1) > CFG_MAX_PMKID_CACHE) { + prAisSpecBssInfo->u4PmkidCandicateCount --; + } + + i = prAisSpecBssInfo->u4PmkidCandicateCount; + + COPY_MAC_ADDR((PVOID)prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, + (PVOID)prBssDesc->aucBSSID); + + if (prBssDesc->u2RsnCap & MASK_RSNIE_CAP_PREAUTH) { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 1; + DBGLOG(RSN, TRACE, ("Add " MACSTR " with pre-auth to candidate list\n", + MAC2STR(prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); + } + else { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 0; + DBGLOG(RSN, TRACE, ("Add " MACSTR " without pre-auth to candidate list\n", + MAC2STR(prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); + } + + prAisSpecBssInfo->u4PmkidCandicateCount ++; + +} /* rsnUpdatePmkidCandidateList */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the desired entry in +* PMKID cache according to the BSSID +* +* \param[in] pucBssid Pointer to the BSSID +* \param[out] pu4EntryIndex Pointer to place the found entry index +* +* \retval TRUE, if found one entry for specified BSSID +* \retval FALSE, if not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnSearchPmkidEntry ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBssid, + OUT PUINT_32 pu4EntryIndex + ) +{ + UINT_32 i; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnSearchPmkidEntry"); + + ASSERT(pucBssid); + ASSERT(pu4EntryIndex); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (prAisSpecBssInfo->u4PmkidCacheCount > CFG_MAX_PMKID_CACHE) { + return FALSE; + } + + ASSERT(prAisSpecBssInfo->u4PmkidCacheCount <= CFG_MAX_PMKID_CACHE); + + /* Search for desired BSSID */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, pucBssid, + MAC_ADDR_LEN)) { + break; + } + } + + /* If desired BSSID is found, then set the PMKID */ + if (i < prAisSpecBssInfo->u4PmkidCacheCount) { + *pu4EntryIndex = i; + + return TRUE; + } + + return FALSE; +} /* rsnSearchPmkidEntry */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check if there is difference +* between PMKID candicate list and PMKID cache. If there +* is new candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \retval TRUE, if new member in the PMKID candicate list +* \retval FALSe, if no new member in the PMKID candicate list +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnCheckPmkidCandicate ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + UINT_32 i; // Index for PMKID candicate + UINT_32 j; // Indix for PMKID cache + BOOLEAN status = FALSE; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Check for each candicate */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecBssInfo->u4PmkidCacheCount; j++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, + MAC_ADDR_LEN)) { + //DBGLOG(RSN, TRACE, (MACSTR" at PMKID cache!!\n", MAC2STR(prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); + break; + } + } + + /* No entry found in PMKID cache for the candicate, add new one */ + if (j == prAisSpecBssInfo->u4PmkidCacheCount && prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE) { + DBGLOG(RSN, TRACE, ("Add "MACSTR" to PMKID cache!!\n", MAC2STR(prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); + kalMemCopy((PVOID)prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.arBSSID, + (PVOID)prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, + MAC_ADDR_LEN); + prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].fgPmkidExist = FALSE; + prAisSpecBssInfo->u4PmkidCacheCount++; + + status = TRUE; + } + } + + return status; +} /* rsnCheckPmkidCandicate */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to wait a duration to indicate the pre-auth AP candicate +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnIndicatePmkidCand ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ) +{ + DBGLOG(RSN, EVENT, ("Security - Time to indicate the PMKID cand.\n")); + + /* If the authentication mode is WPA2 and indication PMKID flag + is available, then we indicate the PMKID candidate list to NDIS and + clear the flag, indicatePMKID */ + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnGeneratePmkidIndication(prAdapter); + } + + return; +} /* end of rsnIndicatePmkidCand() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check the BSS Desc at scan result +* with pre-auth cap at wpa2 mode. If there +* is candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \param[in] prBss The BSS Desc at scan result +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnCheckPmkidCache ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ) +{ + P_AIS_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + ASSERT(prBss); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if ((prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && + (prConnSettings->eAuthMode == AUTH_MODE_WPA2)) { + rsnSelectPmkidCandidateList(prAdapter, prBss); + + /* Set indication flag of PMKID to TRUE, and then connHandleNetworkConnection() + will indicate this later */ + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, ("Prepare a timer to indicate candidate PMKID Candidate\n")); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate an PMKID candidate list +* indication to NDIS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4Flags PMKID candidate list event: +* PARAM_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGeneratePmkidIndication ( + IN P_ADAPTER_T prAdapter + ) +{ + P_PARAM_STATUS_INDICATION_T prStatusEvent; + P_PARAM_PMKID_CANDIDATE_LIST_T prPmkidEvent; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + UINT_8 i, j = 0, count = 0; + UINT_32 u4LenOfUsedBuffer; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + ASSERT(prAdapter); + + prStatusEvent = + (P_PARAM_STATUS_INDICATION_T)prAdapter->aucIndicationEventBuffer; + + /* Status type: PMKID Candidatelist Event */ + prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + ASSERT(prStatusEvent); + + prPmkidEvent = (P_PARAM_PMKID_CANDIDATE_LIST_T)(&prStatusEvent->eStatusType + 1); + ASSERT(prPmkidEvent); + + prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prAisSpecificBssInfo); + + for (i = 0; i < prAisSpecificBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecificBssInfo->u4PmkidCacheCount; j++) { + if (EQUAL_MAC_ADDR( prAisSpecificBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid) && + (prAisSpecificBssInfo->arPmkidCache[j].fgPmkidExist == TRUE)){ + break; + } + } + if (count >= CFG_MAX_PMKID_CACHE) { + break; + } + + if (j == prAisSpecificBssInfo->u4PmkidCacheCount) { + kalMemCopy((PVOID)prPmkidEvent->arCandidateList[count].arBSSID, + (PVOID)prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid, + PARAM_MAC_ADDR_LEN); + prPmkidEvent->arCandidateList[count].u4Flags = + prAisSpecificBssInfo->arPmkidCandicate[i].u4PreAuthFlags; + DBGLOG(RSN, TRACE, (MACSTR" %d\n", MAC2STR(prPmkidEvent->arCandidateList[count].arBSSID), + prPmkidEvent->arCandidateList[count].u4Flags)); + count++; + } + } + + /* PMKID Candidate List */ + prPmkidEvent->u4Version = 1; + prPmkidEvent->u4NumCandidates = count; + DBGLOG(RSN, TRACE, ("rsnGeneratePmkidIndication #%d\n", prPmkidEvent->u4NumCandidates)); + u4LenOfUsedBuffer = sizeof(ENUM_STATUS_TYPE_T) + (2 * sizeof(UINT_32)) + + (count * sizeof(PARAM_PMKID_CANDIDATE_T)); + //dumpMemory8((PUINT_8)prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAdapter->aucIndicationEventBuffer, + u4LenOfUsedBuffer); + +} /* rsnGeneratePmkidIndication */ +#endif + +#if CFG_SUPPORT_WPS2 +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WSC IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WSC IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID +rsnGenerateWSCIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 221 :0xDD */ + if (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWSCAssocInfoIE, prAdapter->prGlueInfo->u2WSCAssocInfoIELen); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WSCAssocInfoIELen; + } + +} +#endif + + +#if CFG_SUPPORT_802_11W + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the Bip Key installed or not +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +rsnCheckBipKeyInstalled ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + if (prStaRec && prStaRec->ucNetTypeIndex == (UINT_8)NETWORK_TYPE_AIS_INDEX) + return prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to check the Sa query timeout. +* +* +* \note +* Called by: AIS module, Handle by Sa Quert timeout +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +rsnCheckSaQueryTimeout ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + UINT_32 now; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, + prBssSpecInfo->u4SaQueryStart, + TU_TO_MSEC(1000))) { + LOG_FUNC("association SA Query timed out\n"); + + prBssSpecInfo->ucSaQueryTimedOut = 1; + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + prBssSpecInfo->pucSaQueryTransId = NULL; + prBssSpecInfo->u4SaQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + /* Re-connect */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query timer. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStartSaQueryTimer ( + IN P_ADAPTER_T prAdapter + ) +{ + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prTxFrame; + UINT_16 u2PayloadLen; + PUINT_8 pucTmp = NULL; + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + ASSERT(prBssInfo); + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + LOG_FUNC("MFP: Start Sa Query\n"); + + if (prBssSpecInfo->u4SaQueryCount > 0 && + rsnCheckSaQueryTimeout(prAdapter)) { + LOG_FUNC("MFP: u4SaQueryCount count =%d\n", prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prBssSpecInfo->u4SaQueryCount == 0) { + GET_CURRENT_SYSTIME(&prBssSpecInfo->u4SaQueryStart); + } + + if (prBssSpecInfo->u4SaQueryCount) { + pucTmp = kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!pucTmp) { + DBGLOG(RSN, INFO, ("MFP: Fail to alloc tmp buffer for backup sa query id\n")); + return; + } + kalMemCopy(pucTmp, prBssSpecInfo->pucSaQueryTransId, prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + } + + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + + ucTransId[0] = (UINT_8)(kalRandomNumber() & 0xFF); + ucTransId[1] = (UINT_8)(kalRandomNumber() & 0xFF); + + kalMemCopy(prTxFrame->ucTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + prBssSpecInfo->u4SaQueryCount++; + + prBssSpecInfo->pucSaQueryTransId = kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!prBssSpecInfo->pucSaQueryTransId) { + DBGLOG(RSN, INFO, ("MFP: Fail to alloc buffer for sa query id list\n")); + return; + } + + if (pucTmp) { + kalMemCopy(prBssSpecInfo->pucSaQueryTransId, pucTmp, (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + kalMemCopy(&prBssSpecInfo->pucSaQueryTransId[(prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN], + ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + kalMemFree(pucTmp, VIR_MEM_TYPE, (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + } + else { + kalMemCopy(prBssSpecInfo->pucSaQueryTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + } + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + //4 Update information of MSDU_INFO_T + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + //4 Enqueue the frame to send this action frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, TRACE, ("Set SA Query timer %d (%d sec)\n", prBssSpecInfo->u4SaQueryCount, prBssInfo->u2ObssScanInterval)); + + cnmTimerStartTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer, + TU_TO_MSEC(201)); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStartSaQuery ( + IN P_ADAPTER_T prAdapter + ) +{ + rsnStartSaQueryTimer(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to stop the 802.11w sa query. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStopSaQuery ( + IN P_ADAPTER_T prAdapter + ) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + prBssSpecInfo->pucSaQueryTransId = NULL; + prBssSpecInfo->u4SaQueryCount = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void +rsnSaQueryRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prRxFrame = NULL; + UINT_16 u2PayloadLen; + P_STA_RECORD_T prStaRec; + P_ACTION_SA_QUERY_FRAME prTxFrame; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + ASSERT(prBssInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME)prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + DBGLOG(RSN, TRACE, ("IEEE 802.11: Received SA Query Request from " + MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + + DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, TRACE, ("IEEE 802.11: Ignore SA Query Request " + "from unassociated STA " MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + return; + } + DBGLOG(RSN, TRACE, ("IEEE 802.11: Sending SA Query Response to " + MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + /* SA Query always with protected */ + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_RESPONSE; + + kalMemCopy(prTxFrame->ucTransId, + prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN); + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + //4 Update information of MSDU_INFO_T + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + //4 Enqueue the frame to send this action frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void +rsnSaQueryAction ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_ACTION_SA_QUERY_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + UINT_32 i; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, TRACE, ("IEEE 802.11: Too short SA Query Action " + "frame (len=%lu)\n", (unsigned long) prSwRfb->u2PacketLen)); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, TRACE, ("IEEE 802.11: Unexpected SA Query " + "Action %d\n", prRxFrame->ucAction)); + return; + } + + DBGLOG(RSN, TRACE, ("IEEE 802.11: Received SA Query Response from " + MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + + DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + + for (i = 0; i < prBssSpecInfo->u4SaQueryCount; i++) { + if (kalMemCmp(prBssSpecInfo->pucSaQueryTransId + + i * ACTION_SA_QUERY_TR_ID_LEN, + prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN) == 0) + break; + } + + if (i >= prBssSpecInfo->u4SaQueryCount) { + DBGLOG(RSN, TRACE, ("IEEE 802.11: No matching SA Query " + "transaction identifier found\n")); + return; + } + + DBGLOG(RSN, TRACE, ("Reply to pending SA Query received\n")); + + rsnStopSaQuery(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w mgmt frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnCheckRxMgmt ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 ucSubtype + ) +{ + P_HIF_RX_HEADER_T prHifRxHdr; + BOOLEAN fgUnicast = TRUE; + BOOLEAN fgRobustAction = FALSE; + + prHifRxHdr = prSwRfb->prHifRxHdr; + + if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + if (prAssocReqFrame->aucDestAddr[0] & BIT(0)) + fgUnicast = FALSE; + + LOG_FUNC("QM RX MGT: rsnCheckRxMgmt = %d 0x%x %d ucSubtype=%x\n", fgUnicast, prHifRxHdr->ucReserved, (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC), ucSubtype); + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + /* "Dropped unprotected Robust Action frame from an MFP STA" */ + /* exclude Public Action */ + if (ucSubtype == 13 /* 0x1011: MAC_FRAME_ACTION */) + { + UINT_8 ucAction = *prSwRfb->pucRecvBuff; + if (ucAction != CATEGORY_PUBLIC_ACTION && ucAction != CATEGORY_HT_ACTION) { +#if DBG && CFG_RX_PKTS_DUMP + LOG_FUNC("QM RX MGT: UnProtected Robust Action frame = %d\n", ucAction); +#endif + fgRobustAction = TRUE; + return TRUE; + } + } + if (fgUnicast && ((ucSubtype == 10 /* 0x1010: MAC_FRAME_DISASSOC */) || (ucSubtype == 12 /* 0x1100: MAC_FRAME_DEAUTH */))) { + LOG_FUNC("QM RX MGT: rsnStartSaQuery\n"); + /* MFP test plan 5.3.3.5 */ + rsnStartSaQuery(prAdapter); + return TRUE; + } + } +#if 0 + else { + if (fgUnicast && ((ucSubtype == MAC_FRAME_DISASSOC) || (ucSubtype == MAC_FRAME_DEAUTH))) { + /* This done by function handler */ + //kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + // WLAN_STATUS_MEDIA_DISCONNECT, + // NULL, + // 0); + } + } +#endif + } + return FALSE; +} +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c new file mode 100755 index 000000000000..65eee2b53fe3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c @@ -0,0 +1,2022 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/saa_fsm.c#2 $ +*/ + +/*! \file "saa_fsm.c" + \brief This file defines the FSM for SAA MODULE. + + This file defines the FSM for SAA MODULE. +*/ + + + +/* +** $Log: saa_fsm.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED cases as an explicit trigger for Android framework + * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. + * 2. (Android only) when reassociation-and-non-roaming cases happened, indicate an extra DISCONNECT indication to Android Wi-Fi framework + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * Add debug message about 40MHz bandwidth allowed + * + * 05 12 2011 cp.wu + * [WCXRP00000720] [MT6620 Wi-Fi][Driver] Do not do any further operation in case STA-REC has been invalidated before SAA-FSM starts to roll + * check for valid STA-REC before SAA-FSM starts to roll. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 31 2011 puff.wen + * NULL + * . + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix compile error of after Station Type Macro modification. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 24 2010 chinghwa.yu + * NULL + * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. + * Update saa_fsm for BOW. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 02 2010 yuche.tsai + * NULL + * Add support for P2P join event start. + * + * 07 12 2010 cp.wu + * + * SAA will take a record for tracking request sequence number. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with main branch for reseting to state 1 when associating with another AP + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error when enable WiFi Direct function. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * + * * * Add Connection Policy - Any and Rx Burst Deauth Support for WHQL + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support of Driver STA_RECORD_T activation + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 12 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix compile warning due to declared but not used + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Refine Debug Label + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comment + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the function + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugAAState[AA_STATE_NUM] = { + (PUINT_8)DISP_STRING("AA_STATE_IDLE"), + (PUINT_8)DISP_STRING("SAA_STATE_SEND_AUTH1"), + (PUINT_8)DISP_STRING("SAA_STATE_WAIT_AUTH2"), + (PUINT_8)DISP_STRING("SAA_STATE_SEND_AUTH3"), + (PUINT_8)DISP_STRING("SAA_STATE_WAIT_AUTH4"), + (PUINT_8)DISP_STRING("SAA_STATE_SEND_ASSOC1"), + (PUINT_8)DISP_STRING("SAA_STATE_WAIT_ASSOC2"), + (PUINT_8)DISP_STRING("AAA_STATE_SEND_AUTH2"), + (PUINT_8)DISP_STRING("AAA_STATE_SEND_AUTH4"), + (PUINT_8)DISP_STRING("AAA_STATE_SEND_ASSOC2"), + (PUINT_8)DISP_STRING("AA_STATE_RESOURCE") +}; +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of SAA Module. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] eNextState The value of Next State +* @param[in] prRetainedSwRfb Pointer to the retained SW_RFB_T for JOIN Success +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_AA_STATE_T eNextState, + IN P_SW_RFB_T prRetainedSwRfb + ) +{ + ENUM_AA_STATE_T ePreviousState; + BOOLEAN fgIsTransition; + + + ASSERT(prStaRec); + if(!prStaRec) { + return; + } + + do { + +#if DBG + DBGLOG(SAA, STATE, ("TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], + apucDebugAAState[eNextState])); +#else + DBGLOG(SAA, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n", + DBG_SAA_IDX, + prStaRec->eAuthAssocState, + eNextState)); +#endif + ePreviousState = prStaRec->eAuthAssocState; + + /* NOTE(Kevin): This is the only place to change the eAuthAssocState(except initial) */ + prStaRec->eAuthAssocState = eNextState; + + + fgIsTransition = (BOOLEAN)FALSE; + switch (prStaRec->eAuthAssocState) { + case AA_STATE_IDLE: + { + if (ePreviousState != prStaRec->eAuthAssocState) { /* Only trigger this event once */ + + if (prRetainedSwRfb) { + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, + prRetainedSwRfb) == WLAN_STATUS_SUCCESS) { + } + else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + else { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, + NULL) == WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T)NULL; + } + } + break; + + case SAA_STATE_SEND_AUTH1: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } + else { + prStaRec->ucTxAuthAssocRetryCount++; + + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, + AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) +#else + if (authSendAuthFrame( + prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) +#endif /* CFG_SUPPORT_AAA */ + { + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventTxReqTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH2: + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } + else { + prStaRec->ucTxAuthAssocRetryCount++; + +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, + AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) +#else + if (authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) +#endif /* CFG_SUPPORT_AAA */ + { + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventTxReqTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH4: + break; + + case SAA_STATE_SEND_ASSOC1: + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } + else { + prStaRec->ucTxAuthAssocRetryCount++; + + if (assocSendReAssocReqFrame(prAdapter, prStaRec) != WLAN_STATUS_SUCCESS) { + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventTxReqTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_ASSOC2: + break; + + case AA_STATE_RESOURCE: + /* TODO(Kevin) Can setup a timer and send message later */ + break; + + default: + DBGLOG(SAA, ERROR, ("Unknown AA STATE\n")); + ASSERT(0); + break; + } + + } + while (fgIsTransition); + + return; + +} /* end of saaFsmSteps() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmSendEventJoinComplete ( + IN P_ADAPTER_T prAdapter, + IN WLAN_STATUS rJoinStatus, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prStaRec); + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + /* Store limitation about 40Mhz bandwidth capability during association */ + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) { + prBssInfo->fg40mBwAllowed = prBssInfo->fgAssoc40mBwAllowed; + } + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + if(prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) { + return WLAN_STATUS_RESOURCES; + } + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (IS_STA_IN_P2P(prStaRec))) { + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) { + return WLAN_STATUS_RESOURCES; + } + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if(prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + //@TODO: BOW handler + + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) { + return WLAN_STATUS_RESOURCES; + } + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif + else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + +} /* end of saaFsmSendEventJoinComplete() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventStart ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SAA_FSM_START_T prSaaFsmStartMsg; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmStartMsg = (P_MSG_SAA_FSM_START_T)prMsgHdr; + prStaRec = prSaaFsmStartMsg->prStaRec; + + if((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, ("EVENT-START: Trigger SAA FSM.\n")); + + /* record sequence number of request message */ + prStaRec->ucAuthAssocReqSeqNum = prSaaFsmStartMsg->ucSeqNum; + + cnmMemFree(prAdapter, prMsgHdr); + + //4 <1> Validation of SAA Start Event + if (!IS_AP_STA(prStaRec)) { + + DBGLOG(SAA, ERROR, ("EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType)); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(prAdapter, WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + + //4 <2> The previous JOIN process is not completed ? + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, ("EVENT-START: Reentry of SAA Module.\n")); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + + //4 <3> Reset Status Code and Time + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T)NULL; + } + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + +#if CFG_PRIVACY_MIGRATION + //4 <4> Init the sec fsm + secFsmInit(prAdapter, prStaRec); +#endif + + //4 <5> Reset the STA STATE + /* Update Station Record - Class 1 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for Reconnect issue - + * We won't deactivate the same STA_RECORD_T and then activate it again for the + * case of reconnection. + */ + //cnmStaRecChangeState(prStaRec, STA_STATE_1); + + //4 <6> Decide if this BSS 20/40M bandwidth is allowed + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = + cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex); + } + else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, INFO, ("STA 40mAllowed=%d\n", prBssInfo->fgAssoc40mBwAllowed)); + } + + //4 <7> Trigger SAA FSM + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T)NULL); + + return; +} /* end of saaFsmRunEventStart() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth1/Auth3/AssocReq) Event of SAA FSM. +* +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + + P_STA_RECORD_T prStaRec; + ENUM_AA_STATE_T eNextState; + + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if(!prStaRec) { + return WLAN_STATUS_INVALID_PACKET; + } + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, ("EVENT-TX DONE: Current Time = %ld\n", kalGetTimeTick())); + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, + prMsduInfo, + AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) { + break; + } + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH2; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventRxRespTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Strictly check the outgoing frame is matched with current JOIN STATE */ + if (authCheckTxAuthFrame(prAdapter, + prMsduInfo, + AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) { + break; + } + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH4; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventRxRespTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + break; + + case SAA_STATE_SEND_ASSOC1: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocReqFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) { + break; + } + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_ASSOC2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC)saaFsmRunEventRxRespTimeOut, + (UINT_32)prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rTxReqDoneOrRxRespTimer), + TU_TO_MSEC(DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + break; + + default: + break; /* Ignore other cases */ + } + + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventTxDone() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Tx Request Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventTxReqTimeOut ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + ASSERT(prStaRec); + if(!prStaRec) { + return; + } + + DBGLOG(SAA, LOUD, ("EVENT-TIMER: TX REQ TIMEOUT, Current Time = %ld\n", kalGetTimeTick())); + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_SEND_ASSOC1: + saaFsmSteps(prAdapter, prStaRec, prStaRec->eAuthAssocState, (P_SW_RFB_T)NULL); + break; + + default: + return; + } + + return; +} /* end of saaFsmRunEventTxReqTimeOut() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Rx Response Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventRxRespTimeOut ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + ENUM_AA_STATE_T eNextState; + + + DBGLOG(SAA, LOUD, ("EVENT-TIMER: RX RESP TIMEOUT, Current Time = %ld\n", kalGetTimeTick())); + + ASSERT(prStaRec); + if(!prStaRec) { + return; + } + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_WAIT_AUTH2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH1; + break; + + case SAA_STATE_WAIT_AUTH4: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH3; + break; + + case SAA_STATE_WAIT_ASSOC2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_ASSOC1; + break; + + default: + break; /* Ignore other cases */ + } + + + if (eNextState != prStaRec->eAuthAssocState) { + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + + return; +} /* end of saaFsmRunEventRxRespTimeOut() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventRxAuth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + ASSERT(0); + return; + } + + if (!IS_AP_STA(prStaRec)) { + return; + } + + switch(prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_WAIT_AUTH2: + /* Check if the incoming frame is what we are waiting for */ + if (authCheckRxAuthFrameStatus(prAdapter, + prSwRfb, + AUTH_TRANSACTION_SEQ_2, + &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); + + if (prStaRec->ucAuthAlgNum == + (UINT_8)AUTH_ALGORITHM_NUM_SHARED_KEY) { + + eNextState = SAA_STATE_SEND_AUTH3; + } + else { + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } + } + else { + DBGLOG(SAA, INFO, ("Auth Req was rejected by ["MACSTR"], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode)); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_WAIT_AUTH4: + /* Check if the incoming frame is what we are waiting for */ + if (authCheckRxAuthFrameStatus(prAdapter, + prSwRfb, + AUTH_TRANSACTION_SEQ_4, + &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); /* Add for 802.11r handling */ + + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } + else { + DBGLOG(SAA, INFO, ("Auth Req was rejected by ["MACSTR"], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode)); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T)NULL); + } + break; + + default: + break; /* Ignore other cases */ + } + + return; +} /* end of saaFsmRunEventRxAuth() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx (Re)Association Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS if the status code was not success +* @retval WLAN_STATUS_BUFFER_RETAINED if the status code was success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventRxAssoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + P_SW_RFB_T prRetainedSwRfb = (P_SW_RFB_T)NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + ASSERT(0); + return rStatus; + } + + if (!IS_AP_STA(prStaRec)) { + return rStatus; + } + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_ASSOC1: + case SAA_STATE_WAIT_ASSOC2: + /* TRUE if the incoming frame is what we are waiting for */ + if (assocCheckRxReAssocRspFrameStatus(prAdapter, + prSwRfb, + &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* Update Station Record - Class 3 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for roaming issue - + * We should deactivate the STA_RECORD_T of previous AP before + * activate new one in Driver. + */ + //cnmStaRecChangeState(prStaRec, STA_STATE_3); + + prStaRec->ucJoinFailureCount = 0; // Clear history. + + prRetainedSwRfb = prSwRfb; + rStatus = WLAN_STATUS_PENDING; + } + else { + DBGLOG(SAA, INFO, ("Assoc Req was rejected by ["MACSTR"], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode)); + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + eNextState = AA_STATE_IDLE; + + saaFsmSteps(prAdapter, prStaRec, eNextState, prRetainedSwRfb); + } + break; + + default: + break; /* Ignore other cases */ + } + + return rStatus; + +} /* end of saaFsmRunEventRxAssoc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Deauth Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain deauthentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventRxDeauth ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_STA_RECORD_T prStaRec; +#if DBG + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; +#endif /* DBG */ + + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + +#if DBG + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + + DBGLOG(SAA, INFO, ("Rx Deauth frame from BSSID=["MACSTR"].\n", + MAC2STR(prDeauthFrame->aucBSSID))); +#endif /* DBG */ + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + + if (!IS_AP_STA(prStaRec)) { + break; + } + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState > STA_STATE_1) { + + /* Check if this is the AP we are associated or associating with */ + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + if (STA_STATE_3 == prStaRec->ucStaState) { + P_MSG_AIS_ABORT_T prAisAbortMsg; + + /* NOTE(Kevin): Change state immediately to avoid starvation of + * MSG buffer because of too many deauth frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + break; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_DEAUTHENTICATED; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } + else { + + /* TODO(Kevin): Joining Abort */ + } + + } + + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDeauthentication(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); + } +#endif + else { + ASSERT(0); + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDeauth() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Disassociation Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain disassociation frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventRxDisassoc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_STA_RECORD_T prStaRec; +#if DBG + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; +#endif /* DBG */ + + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + +#if DBG + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + + DBGLOG(SAA, INFO, ("Rx Disassoc frame from BSSID=["MACSTR"].\n", + MAC2STR(prDisassocFrame->aucBSSID))); +#endif /* DBG */ + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + + if (!IS_AP_STA(prStaRec)) { + break; + } + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState > STA_STATE_1) { + + /* Check if this is the AP we are associated or associating with */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + if (STA_STATE_3 == prStaRec->ucStaState) { + P_MSG_AIS_ABORT_T prAisAbortMsg; + + prAisAbortMsg = (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + break; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } + else { + + /* TODO(Kevin): Joining Abort */ + } + + } + + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDisassociation(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + /* TODO(Kevin) */ + } +#endif + else { + ASSERT(0); + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDisassoc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Abort Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Abort Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmRunEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SAA_FSM_ABORT_T prSaaFsmAbortMsg; + P_STA_RECORD_T prStaRec; + + + ASSERT(prMsgHdr); + + prSaaFsmAbortMsg = (P_MSG_SAA_FSM_ABORT_T)prMsgHdr; + prStaRec = prSaaFsmAbortMsg->prStaRec; + + ASSERT(prStaRec); + if(!prStaRec) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(SAA, LOUD, ("EVENT-ABORT: Stop SAA FSM.\n")); + + cnmMemFree(prAdapter, prMsgHdr); + + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* Cancel JOIN relative Timer */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { +#if DBG + DBGLOG(SAA, LOUD, ("EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState])); +#else + DBGLOG(SAA, LOUD, ("EVENT-ABORT: Previous Auth/Assoc State == %d.\n", + prStaRec->eAuthAssocState)); +#endif + } + +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec, FALSE); +#endif + + return; +} /* end of saaFsmRunEventAbort() */ + + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +joinFsmRunEventJoinTimeOut ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, ("JOIN EVENT: JOIN TIMEOUT\n")); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, + prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) { + joinAdoptParametersFromCurrentBss(prAdapter); + } + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinAdoptParametersFromPeerBss ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + //4 <1> Adopt Peer BSS' PHY TYPE + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, ("Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS")); + + + //4 <2> Adopt Peer BSS' Frequency(Band/Channel) + DBGLOG(JOIN, INFO, ("Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand)); + + nicSwitchChannel(prAdapter, + prBssDesc->eBand, + prBssDesc->ucChannelNum, + 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + + return; +} /* end of joinAdoptParametersFromPeerBss() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinAdoptParametersFromCurrentBss ( + IN P_ADAPTER_T prAdapter + ) +{ + //P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; + P_BSS_INFO_T prBssInfo; + + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + //4 <1> Adopt current BSS' PHY TYPE + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + //4 <2> Adopt current BSS' Frequency(Band/Channel) + DBGLOG(JOIN, INFO, ("Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand)); + + nicSwitchChannel(prAdapter, + prBssInfo->eBand, + prBssInfo->ucChnl, + 10); + return; +} /* end of joinAdoptParametersFromCurrentBss() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +joinComplete ( + IN P_ADAPTER_T prAdapter + ) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +//4 <1> Update Connecting & Connected Flag of BSS_DESC_T. + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prAdapter->rConnSettings.aucSSID, + prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) { + prBssDesc->fgIsHiddenSSID = FALSE; + } +#if DBG + else { + ASSERT(0); + } +#endif /* DBG */ + + DBGLOG(JOIN, INFO, ("Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID)); + } + + +//4 <2> Update BSS_INFO_T from BSS_DESC_T + //4 <2.A> PHY Type + prBssInfo->ePhyType = prBssDesc->ePhyType; + + //4 <2.B> BSS Type + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + //4 <2.C> BSSID + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, ("JOIN to BSSID: ["MACSTR"]\n", MAC2STR(prBssDesc->aucBSSID))); + + + //4 <2.D> SSID + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + + //4 <2.E> Channel / Band information. + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + //4 <2.F> RSN/WPA information. + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) { + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + } + else { + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + } + + //4 <2.G> Beacon interval. + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + //4 <2.H> DTIM period. + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + //4 <2.I> ERP Information + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && // Our BSS's PHY_TYPE is ERP now. + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } + else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + //4 <2.J> Country inforamtion of the associated AP + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + //4 <2.K> Signal Power of the associated AP + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + //4 <2.L> Capability Field of the associated AP + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, ("prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi)); + + +//4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC + //4 <3.A> Association ID + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + //4 <3.B> WMM Infomation + if (prAdapter->fgIsEnableWMM && + (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T)); + } + else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } + else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + + //4 <3.C> Operational Rate Set & BSS Basic Rate Set + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + + //4 <3.D> Short Preamble + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) { + prBssInfo->fgUseShortPreamble = FALSE; + } + else { + prBssInfo->fgUseShortPreamble = TRUE; + } + } + else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } + else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, ("prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble)); + + + //4 <3.E> Short Slot Time + prBssInfo->fgUseShortSlotTime = + prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, ("prBssInfo->fgUseShortSlotTime = %d\n", + prBssInfo->fgUseShortSlotTime)); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + + //4 <3.F> Update Tx Rate for Control Frame + bssUpdateTxRateForControlFrame(prAdapter); + + + //4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). + //if (prAdapter->fgIsEnableRoaming) /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) { + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + } + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) { + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + } + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + + //4 <3.H> Update Parameter for TX Fragmentation Threshold +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + + +//4 <4> Update STA_RECORD_T + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + //4 <4.A> Desired Rate Set + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } + else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, + &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, + &prStaRec->ucCurrRate1Index)) { + ASSERT(0); + } + } + + DBGLOG(JOIN, INFO, ("prStaRec->ucCurrRate1Index = %d\n", + prStaRec->ucCurrRate1Index)); + + //4 <4.B> Preamble Mode + prStaRec->fgIsShortPreambleOptionEnable = + prBssInfo->fgUseShortPreamble; + + //4 <4.C> QoS Flag + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else { + ASSERT(0); + } +#endif /* DBG */ + + +//4 <5> Update NIC + //4 <5.A> Update BSSID & Operation Mode + nicSetupBSS(prAdapter, prBssInfo); + + //4 <5.B> Update WLAN Table. + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) { + ASSERT(FALSE); + } + + //4 <5.C> Update Desired Rate Set for BT. +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) { + txRateSetInitForBT(prAdapter, prStaRec); + } +#endif /* CFG_TX_FRAGMENT */ + + //4 <5.D> TX AC Parameter and TX/RX Queue Control + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } + else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, + prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + + #if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8)TXQ_DATA_MASK, (UINT_8)NULL); + #endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) { + nicTxRetransmitOfOsSendQue(prAdapter); + } + + #if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); + #endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + + +//4 <6> Setup CONNECTION flag. + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) { + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + } + else { + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, + (PVOID)NULL, + 0); + + return; +} /* end of joinComplete() */ +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c new file mode 100755 index 000000000000..cd52555aab17 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c @@ -0,0 +1,2955 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#3 $ +*/ + +/*! \file "scan.c" + \brief This file defines the scan profile and the processing function of + scan result for SCAN Module. + + The SCAN Profile selection is part of SCAN MODULE and responsible for defining + SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. + In this file we also define the process of SCAN Result including adding, searching + and removing SCAN record from the list. +*/ + + + +/* +** $Log: scan.c $ +** +** 01 16 2013 yuche.tsai +** [ALPS00431980] [WFD]Aupus one ?play game 10 minitues?wfd connection automaticlly disconnect +** Fix possible FW assert issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 25 2012 cp.wu + * [WCXRP00001258] [MT6620][MT5931][MT6628][Driver] Do not use stale scan result for deciding connection target + * drop off scan result which is older than 5 seconds when choosing which BSS to join + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * correct typo. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type. + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 11 23 2011 cp.wu + * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection + * add compile option to disable beacon content change detection. + * + * 11 04 2011 cp.wu + * [WCXRP00001085] [MT6628 Wi-Fi][Driver] deprecate old BSS-DESC if timestamp is reset with received beacon/probe response frames + * deprecate old BSS-DESC when timestamp in received beacon/probe response frames showed a smaller value than before + * + * 10 11 2011 cm.chang + * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter + * Ignore HT OP IE if its length field is not valid + * + * 09 30 2011 cp.wu + * [WCXRP00001021] [MT5931][Driver] Correct scan result generation for conversion between BSS type and operation mode + * correct type casting issue. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 10 2011 cp.wu + * [WCXRP00000922] [MT6620 Wi-Fi][Driver] traverse whole BSS-DESC list for removing + * traverse whole BSS-DESC list because BSSID is not unique anymore. + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * for multiple BSS descriptior detecting issue: + * 1) check BSSID for infrastructure network + * 2) check SSID for AdHoc network + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * check for BSSID for beacons used to update DTIM + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * do not check BSS descriptor for connected flag due to linksys's hidden SSID will use another BSS descriptor and never connected + * + * 07 11 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * just pass beacons with the same BSSID. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 28 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * Do not check for SSID as beacon content change due to the existence of single BSSID with multiple SSID AP configuration + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * 1. correct logic + * 2. replace only BSS-DESC which doesn't have a valid SSID. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * remove unused temporal variable reference. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 06 02 2011 cp.wu + * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels + * filter out BSS in disallowed channel by + * 1. do not add to scan result array if BSS is at disallowed channel + * 2. do not allow to search for BSS-DESC in disallowed channels + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Refine range of valid channel number + * + * 05 02 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Take parsed result for channel information instead of hardware channel number passed from firmware domain + * take parsed result for generating scanning result with channel information. + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Check if channel is valided before record ing BSS channel + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 03 25 2011 yuche.tsai + * NULL + * Always update Bss Type, for Bss Type for P2P Network is changing every time. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix concurrent issue when AIS scan result would overwrite p2p scan result. + * + * 03 14 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * filtering out other BSS coming from adjacent channels + * + * 03 11 2011 chinglan.wang + * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. + * . + * + * 03 11 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * implement beacon change detection by checking SSID and supported rate. + * + * 02 22 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC big endian issue. + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix scan channel extension issue when p2p module is not registered. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 21 2011 cp.wu + * [WCXRP00000380] [MT6620 Wi-Fi][Driver] SSID information should come from buffered BSS_DESC_T rather than using beacon-carried information + * SSID should come from buffered prBssDesc rather than beacon-carried information + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix compile error. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Memfree for P2P Descriptor & P2P Descriptor List. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Free P2P Descriptor List & Descriptor under BSS Descriptor. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * 1) correct typo in scan.c + * 2) TX descriptors, RX descriptos and management buffer should use virtually continous buffer instead of physically contineous one + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * while being unloaded, clear all pending interrupt then set LP-own to firmware + * + * 12 21 2010 cp.wu + * [WCXRP00000280] [MT6620 Wi-Fi][Driver] Enable BSS selection with best RCPI policy in SCN module + * SCN: enable BEST RSSI selection policy support + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 11 03 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Refine the HT rate disallow TKIP pairwise cipher . + * + * 10 12 2010 cp.wu + * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out beacons which is received on the folding frequency + * trust HT IE if available for 5GHz band + * + * 10 11 2010 cp.wu + * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out beacons which is received on the folding frequency + * add timing and strenght constraint for filtering out beacons with same SSID/TA but received on different channels + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 10 01 2010 yuche.tsai + * NULL + * [MT6620 P2P] Fix Big Endian Issue when parse P2P device name TLV. + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * When indicate scan result, append IE buffer information in the scan result. + * + * 09 03 2010 yuche.tsai + * NULL + * 1. Update Beacon RX count when running SLT. + * 2. Ignore Beacon when running SLT, would not update information from Beacon. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * 1. Fix P2P Descriptor List to be a link list, to avoid link corrupt after Bss Descriptor Free. + * 2.. Fix P2P Device Name Length BE issue. + * + * 08 23 2010 yuche.tsai + * NULL + * Add P2P Device Found Indication to supplicant + * + * 08 20 2010 cp.wu + * NULL + * reset BSS_DESC_T variables before parsing IE due to peer might have been reconfigured. + * + * 08 20 2010 yuche.tsai + * NULL + * Workaround for P2P Descriptor Infinite loop issue. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 yuche.tsai + * NULL + * Modify code of processing Probe Resonse frame for P2P. + * + * 08 12 2010 yuche.tsai + * NULL + * Add function to get P2P descriptor of BSS descriptor directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Modify Scan result processing for P2P module. + * + * 08 05 2010 yuche.tsai + * NULL + * Update P2P Device Discovery result add function. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 26 2010 yuche.tsai + * + * Add support for Probe Request & Response parsing. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 21 2010 yuche.tsai + * + * Fix compile error for SCAN module while disabling P2P feature. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct BSS_DESC_T initialization after allocated. + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * if beacon/probe-resp is received in 2.4GHz bands and there is ELEM_ID_DS_PARAM_SET IE available, + * trust IE instead of RMAC information + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Update P2P Function call. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * RSN/PRIVACY compilation flag awareness correction + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error when enable P2P function. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct when ADHOC support is turned on. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * adding the TKIP disallow join a HT AP code. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add more chance of JOIN retry for BG_SCAN + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add new HW CH macro support + * + * 04 06 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the firmware return the broadcast frame at wrong tc. + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * let the rsn wapi IE always parsing. + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Solve the compile warning for 'return non-void' function + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Fix No PKT_INFO_T issue + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Update outgoing ProbeRequest Frame's TX data rate + * + * 02 23 2010 wh.su + * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver + * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 20 2010 kevin.huang + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * + * Refine Beacon processing, add read RF channel from RX Status + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Modify u2EstimatedExtraIELen for probe request + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add HT cap IE to probe request + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update the process of SCAN Result by adding more Phy Attributes + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function and code for meet the new define + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename u4RSSI to i4RSSI + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Report event of scan result to host + * + * Nov 26 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix SCAN Record update + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status and Integrate with TXM + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add (Ext)Support Rate Set IE to ProbeReq + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed the use of SW_RFB->u2FrameLength + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix uninitial aucMacAddress[] for ProbeReq + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scanSearchBssDescByPolicy() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Send Probe Request Frame + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define REPLICATED_BEACON_TIME_THRESHOLD (3000) +#define REPLICATED_BEACON_FRESH_PERIOD (10000) +#define REPLICATED_BEACON_STRENGTH_THRESHOLD (32) + +#define ROAMING_NO_SWING_RCPI_STEP (10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used by SCN to initialize its variables +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnInit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SCAN_INFO_T prScanInfo; + P_BSS_DESC_T prBSSDesc; + PUINT_8 pucBSSBuff; + UINT_32 i; + + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; + + + DBGLOG(SCN, INFO, ("->scnInit()\n")); + + //4 <1> Reset STATE and Message List + prScanInfo->eCurrentState = SCAN_STATE_IDLE; + + prScanInfo->rLastScanCompletedTime = (OS_SYSTIME)0; + + LINK_INITIALIZE(&prScanInfo->rPendingMsgList); + + + //4 <2> Reset link list of BSS_DESC_T + kalMemZero((PVOID) pucBSSBuff, SCN_MAX_BUFFER_SIZE); + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (P_BSS_DESC_T)pucBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); + + pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); + } + /* Check if the memory allocation consist with this initialization function */ + ASSERT(((UINT_32)pucBSSBuff - (UINT_32)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); + + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + return; +} /* end of scnInit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used by SCN to uninitialize its variables +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnUninit ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SCAN_INFO_T prScanInfo; + + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + DBGLOG(SCN, INFO, ("->scnUninit()\n")); + + //4 <1> Reset STATE and Message List + prScanInfo->eCurrentState = SCAN_STATE_IDLE; + + prScanInfo->rLastScanCompletedTime = (OS_SYSTIME)0; + + /* NOTE(Kevin): Check rPendingMsgList ? */ + + //4 <2> Reset link list of BSS_DESC_T + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + + return; +} /* end of scnUninit() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ) +{ + return scanSearchBssDescByBssidAndSsid(prAdapter, + aucBSSID, + FALSE, + NULL); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T)NULL; + + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if(fgCheckSsid == FALSE || prSsid == NULL) { + return prBssDesc; + } + else { + if(EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prSsid->aucSsid, + prSsid->u4SsidLen)) { + return prBssDesc; + } + else if(prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + else { + /* 20120206 frog: Equal BSSID but not SSID, SSID not hidden, SSID must be updated. */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prSsid->aucSsid, + prSsid->u4SsidLen); + return prBssDesc; + } + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByTA ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[] + ) +{ + return scanSearchBssDescByTAAndSsid(prAdapter, + aucSrcAddr, + FALSE, + NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T)NULL; + + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if(fgCheckSsid == FALSE || prSsid == NULL) { + return prBssDesc; + } + else { + if(EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prSsid->aucSsid, + prSsid->u4SsidLen)) { + return prBssDesc; + } + else if(prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDesc ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[] + ) +{ + return scanSearchExistingBssDescWithSsid(prAdapter, + eBSSType, + aucBSSID, + aucSrcAddr, + FALSE, + NULL); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], + IN BOOLEAN fgCheckSsid, + IN P_PARAM_SSID_T prSsid + ) +{ + P_SCAN_INFO_T prScanInfo; + P_BSS_DESC_T prBssDesc, prIBSSBssDesc; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + + switch (eBSSType) { + case BSS_TYPE_P2P_DEVICE: + fgCheckSsid = FALSE; + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_BOW_DEVICE: + { + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + + /* if (eBSSType == prBssDesc->eBSSType) */ + + return prBssDesc; + } + + case BSS_TYPE_IBSS: + { + prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid); + + /* NOTE(Kevin): + * Rules to maintain the SCAN Result: + * For AdHoc - + * CASE I We have TA1(BSSID1), but it change its BSSID to BSSID2 + * -> Update TA1 entry's BSSID. + * CASE II We have TA1(BSSID1), and get TA1(BSSID1) again + * -> Update TA1 entry's contain. + * CASE III We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or + * later, TA2 merge into TA1, we get TA2(BSSID1) + * -> Remove TA2 first and then replace TA1 entry's TA with TA2, Still have only one entry of BSSID. + * CASE IV We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1. + * -> Replace TA1 entry's TA with TA2, Still have only one entry. + * CASE V New IBSS + * -> Add this one to SCAN result. + */ + if (prBssDesc) { + if ((!prIBSSBssDesc) || // CASE I + (prBssDesc == prIBSSBssDesc)) { // CASE II + + return prBssDesc; + } + else { // CASE III + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + + + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + return prIBSSBssDesc; + } + } + + if (prIBSSBssDesc) { // CASE IV + + return prIBSSBssDesc; + } + + // CASE V + break; // Return NULL; + } + + default: + break; + } + + + return (P_BSS_DESC_T)NULL; + +} /* end of scanSearchExistingBssDesc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given Remove Policy. +* +* @param[in] u4RemovePolicy Remove Policy. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveBssDescsByPolicy ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4RemovePolicy + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + //DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", + //prBSSDescList->u4NumElem)); + + if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { + P_BSS_DESC_T prBSSDescNext; + OS_SYSTIME rCurrentTime; + + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC)) ) { + + //DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): MAC: "MACSTR", Current Time = %08lx, Update Time = %08lx\n", + //prBssDesc, MAC2STR(prBssDesc->aucBSSID), rCurrentTime, prBssDesc->rUpdateTime)); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + } + else if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { + P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T)NULL; + + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (!prBssDesc->fgIsHiddenSSID) { + continue; + } + + if (!prBssDescOldest) { /* 1st element */ + prBssDescOldest = prBssDesc; + continue; + } + + if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) { + prBssDescOldest = prBssDesc; + } + } + + if (prBssDescOldest) { + + //DBGLOG(SCN, TRACE, ("Remove OLDEST HIDDEN BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n", + //prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime)); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry); + } + } + else if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { + P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T)NULL; + P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T)NULL; + UINT_32 u4SameSSIDCount = 0; + + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if ((!prBssDesc->fgIsHiddenSSID) && + (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen))) { + + u4SameSSIDCount++; + + if (!prBssDescWeakestSameSSID) { + prBssDescWeakestSameSSID = prBssDesc; + } + else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) { + prBssDescWeakestSameSSID = prBssDesc; + } + } + + if (!prBssDescWeakest) { /* 1st element */ + prBssDescWeakest = prBssDesc; + continue; + } + + if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) { + prBssDescWeakest = prBssDesc; + } + + } + + if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) && + (prBssDescWeakestSameSSID)) { + prBssDescWeakest = prBssDescWeakestSameSSID; + } + + if (prBssDescWeakest) { + + //DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n", + //prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime)); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescWeakest->rLinkEntry); + } + } + else if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { + P_BSS_DESC_T prBSSDescNext; + + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + + } + + return; + +} /* end of scanRemoveBssDescsByPolicy() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given BSSID. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + P_BSS_DESC_T prBSSDescNext; + + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + + return; +} /* end of scanRemoveBssDescByBssid() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given band configuration +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBand Given band +* @param[in] eNetTypeIndex AIS - Remove IBSS/Infrastructure BSS +* BOW - Remove BOW BSS +* P2P - Remove P2P BSS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveBssDescByBandAndNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + P_BSS_DESC_T prBSSDescNext; + BOOLEAN fgToRemove; + + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + + if(eBand == BAND_NULL) { + return; /* no need to do anything, keep all scan result */ + } + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + fgToRemove = FALSE; + + if(prBssDesc->eBand == eBand) { + switch (eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + if((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P_INDEX: + if(prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_BOW_INDEX: + if(prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) { + fgToRemove = TRUE; + } + break; + + default: + ASSERT(0); + break; + } + } + + if(fgToRemove == TRUE) { + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + + return; +} /* end of scanRemoveBssDescByBand() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. +* +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveConnFlagOfBssDescByBssid ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[] + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + + return; + +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate new BSS_DESC_T +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanAllocateBssDesc ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); + + if (prBssDesc) { + P_LINK_T prBSSDescList; + + kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); + +#if CFG_ENABLE_WIFI_DIRECT + LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); + prBssDesc->fgIsP2PPresent = FALSE; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be + * inserted to BSSDescList immediately. + */ + LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); + } + + return prBssDesc; + +} /* end of scanAllocateBssDesc() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T +* with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the receiving frame buffer. +* +* @return Pointer to BSS Descriptor +* NULL if the Beacon/ProbeResp frame is invalid +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanAddToBssDesc ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_BSS_DESC_T prBssDesc = NULL; + UINT_16 u2CapInfo; + ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; + + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)NULL; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T)NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T)NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_8 ucHwChannelNum = 0; + UINT_8 ucIeDsChannelNum = 0; + UINT_8 ucIeHtChannelNum = 0; + BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE; + PARAM_SSID_T rSsid; + UINT_64 u8Timestamp; + BOOLEAN fgIsNewBssDesc = FALSE; + + UINT_32 i; + UINT_8 ucSSIDChar; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo); + WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp); + + // decide BSS type + switch (u2CapInfo & CAP_INFO_BSS_TYPE) { + case CAP_INFO_ESS: + /* It can also be Group Owner of P2P Group. */ + eBSSType = BSS_TYPE_INFRASTRUCTURE; + break; + + case CAP_INFO_IBSS: + eBSSType = BSS_TYPE_IBSS; + break; + case 0: + /* The P2P Device shall set the ESS bit of the Capabilities field in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) */ + eBSSType = BSS_TYPE_P2P_DEVICE; + break; + +#if CFG_ENABLE_BT_OVER_WIFI + // @TODO: add rule to identify BOW beacons +#endif + + default: + return NULL; + } + + //4 <1.1> Pre-parse SSID IE + pucIE = prWlanBeaconFrame->aucInfoElem; + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16)OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + } + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { + ucSSIDChar = '\0'; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) { + fgIsValidSsid = FALSE; + } + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* Linksys WRK54G/ASUS WL520g - (IE_LEN(pucIE) == n) && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + } + + if (ucSSIDChar) { + fgIsValidSsid = TRUE; + } + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (fgIsValidSsid == TRUE) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } + } + fgEscape = TRUE; + break; + default: + break; + } + + if(fgEscape == TRUE) { + break; + } + } + + + //4 <1.2> Replace existing BSS_DESC_T or allocate a new one + prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter, + eBSSType, + (PUINT_8)prWlanBeaconFrame->aucBSSID, + (PUINT_8)prWlanBeaconFrame->aucSrcAddr, + fgIsValidSsid, + fgIsValidSsid == TRUE ? &rSsid : NULL); + + if (prBssDesc == (P_BSS_DESC_T)NULL) { + fgIsNewBssDesc = TRUE; + + do { + //4 <1.2.1> First trial of allocation + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) { + break; + } + + //4 <1.2.2> Hidden is useless, remove the oldest hidden ssid. (for passive scan) + scanRemoveBssDescsByPolicy(prAdapter, + (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_OLDEST_HIDDEN)); + + //4 <1.2.3> Second tail of allocation + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) { + break; + } + + //4 <1.2.4> Remove the weakest one + /* If there are more than half of BSS which has the same ssid as connection + * setting, remove the weakest one from them. + * Else remove the weakest one. + */ + scanRemoveBssDescsByPolicy(prAdapter, + (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_SMART_WEAKEST)); + + //4 <1.2.5> reallocation + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) { + break; + } + + //4 <1.2.6> no space, should not happen + //ASSERT(0); // still no space available ? + return NULL; + + } + while(FALSE); + + } + else { + OS_SYSTIME rCurrentTime; + + // WCXRP00000091 + // if the received strength is much weaker than the original one, + // ignore it due to it might be received on the folding frequency + + GET_CURRENT_SYSTIME(&rCurrentTime); + + prBssDesc->eBSSType = eBSSType; + + if(HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr) != prBssDesc->ucChannelNum && + prBssDesc->ucRCPI > prSwRfb->prHifRxHdr->ucRcpi) { + + // for signal strength is too much weaker and previous beacon is not stale + if((prBssDesc->ucRCPI - prSwRfb->prHifRxHdr->ucRcpi) >= REPLICATED_BEACON_STRENGTH_THRESHOLD && + rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_FRESH_PERIOD) { + return prBssDesc; + } + // for received beacons too close in time domain + else if(rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) { + return prBssDesc; + } + } + + /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */ + if(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) { + BOOLEAN fgIsConnected, fgIsConnecting; + + /* set flag for indicating this is a new BSS-DESC */ + fgIsNewBssDesc = TRUE; + + /* backup 2 flags for APs which reset timestamp unexpectedly */ + fgIsConnected = prBssDesc->fgIsConnected; + fgIsConnecting = prBssDesc->fgIsConnecting; + scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID); + + prBssDesc = scanAllocateBssDesc(prAdapter); + if (!prBssDesc) { + return NULL; + } + + /* restore */ + prBssDesc->fgIsConnected = fgIsConnected; + prBssDesc->fgIsConnecting = fgIsConnecting; + } + } + + /* NOTE: Keep consistency of Scan Record during JOIN process */ + if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) { + return prBssDesc; + } + + //4 <2> Get information from Fixed Fields + prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */ + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr); + + COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID); + + prBssDesc->u8TimeStamp.QuadPart = u8Timestamp; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval); + + prBssDesc->u2CapInfo = u2CapInfo; + + + //4 <2.1> Retrieve IEs for later parsing + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16)OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + prBssDesc->fgIsIEOverflow = TRUE; + } + else { + prBssDesc->fgIsIEOverflow = FALSE; + } + prBssDesc->u2IELength = u2IELength; + + kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, u2IELength); + + //4 <2.2> reset prBssDesc variables in case that AP has been reconfigured + prBssDesc->fgIsERPPresent = FALSE; + prBssDesc->fgIsHTPresent = FALSE; + prBssDesc->eSco = CHNL_EXT_SCN; + prBssDesc->fgIEWAPI = FALSE; +#if CFG_RSN_MIGRATION + prBssDesc->fgIERSN = FALSE; +#endif +#if CFG_PRIVACY_MIGRATION + prBssDesc->fgIEWPA = FALSE; +#endif + + + //4 <3.1> Full IE parsing on SW_RFB_T + pucIE = prWlanBeaconFrame->aucInfoElem; + + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + BOOLEAN fgIsHiddenSSID = FALSE; + ucSSIDChar = '\0'; + + + prIeSsid = (P_IE_SSID_T)pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) { + fgIsHiddenSSID = TRUE; + } + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* Linksys WRK54G/ASUS WL520g - (IE_LEN(pucIE) == n) && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + } + + if (!ucSSIDChar) { + fgIsHiddenSSID = TRUE; + } + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } + + } + break; + + case ELEM_ID_SUP_RATES: + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */ + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) { + prIeSupportedRate = SUP_RATES_IE(pucIE); + } + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) { + ucIeDsChannelNum = DS_PARAM_IE(pucIE)->ucCurrChnl; + } + break; + + case ELEM_ID_TIM: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) { + prBssDesc->ucDTIMPeriod = TIM_IE(pucIE)->ucDTIMPeriod; + } + break; + + case ELEM_ID_IBSS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_IBSS_PARAMETER_SET){ + prBssDesc->u2ATIMWindow = IBSS_PARAM_IE(pucIE)->u2ATIMWindow; + } + break; + +#if 0 //CFG_SUPPORT_802_11D + case ELEM_ID_COUNTRY_INFO: + prBssDesc->prIECountry = (P_IE_COUNTRY_T)pucIE; + break; +#endif + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_ERP) { + prBssDesc->fgIsERPPresent = TRUE; + } + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + if (!prIeExtSupportedRate) { + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + } + break; + +#if CFG_RSN_MIGRATION + case ELEM_ID_RSN: + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &prBssDesc->rRSNInfo)) { + prBssDesc->fgIERSN = TRUE; + prBssDesc->u2RsnCap = prBssDesc->rRSNInfo.u2RsnCap; + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnCheckPmkidCache(prAdapter, prBssDesc); + } + } + break; +#endif + + case ELEM_ID_HT_CAP: + prBssDesc->fgIsHTPresent = TRUE; + break; + + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) { + break; + } + + if ((((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + prBssDesc->eSco = (ENUM_CHNL_EXT_T) + (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO); + } + ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; + + break; + +#if CFG_SUPPORT_WAPI + case ELEM_ID_WAPI: + if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) { + prBssDesc->fgIEWAPI = TRUE; + } + break; +#endif + + case ELEM_ID_VENDOR: // ELEM_ID_P2P, ELEM_ID_WMM + { + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; +#if CFG_PRIVACY_MIGRATION + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && + (u2SubTypeVersion == VERSION_WPA)) { + + if (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo)) { + prBssDesc->fgIEWPA = TRUE; + } + } + } +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + prBssDesc->fgIsP2PPresent = TRUE; + } + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } + break; + + /* no default */ + } + } + + + //4 <3.2> Save information from IEs - SSID + /* Update Flag of Hidden SSID for used in SEARCH STATE. */ + + /* NOTE(Kevin): in current driver, the ucSSIDLen == 0 represent + * all cases of hidden SSID. + * If the fgIsHiddenSSID == TRUE, it means we didn't get the ProbeResp with + * valid SSID. + */ + if (prBssDesc->ucSSIDLen == 0) { + prBssDesc->fgIsHiddenSSID = TRUE; + } + else { + prBssDesc->fgIsHiddenSSID = FALSE; + } + + + //4 <3.3> Check rate information in related IEs. + if (prIeSupportedRate || prIeExtSupportedRate) { + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &prBssDesc->u2OperationalRateSet, + &prBssDesc->u2BSSBasicRateSet, + &prBssDesc->fgIsUnknownBssBasicRate); + } + + + //4 <4> Update information from HIF RX Header + { + prHifRxHdr = prSwRfb->prHifRxHdr; + + ASSERT(prHifRxHdr); + + //4 <4.1> Get TSF comparison result + prBssDesc->fgIsLargerTSF = HIF_RX_HDR_GET_TCL_FLAG(prHifRxHdr); + + //4 <4.2> Get Band information + prBssDesc->eBand = HIF_RX_HDR_GET_RF_BAND(prHifRxHdr); + + //4 <4.2> Get channel and RCPI information + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr); + + if (BAND_2G4 == prBssDesc->eBand) { + + /* Update RCPI if in right channel */ + if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { + + // Receive Beacon/ProbeResp frame from adjacent channel. + if ((ucIeDsChannelNum == ucHwChannelNum) || + (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + } + + // trust channel information brought by IE + prBssDesc->ucChannelNum = ucIeDsChannelNum; + } + else if(ucIeHtChannelNum >= 1 && ucIeHtChannelNum <= 14) { + // Receive Beacon/ProbeResp frame from adjacent channel. + if ((ucIeHtChannelNum == ucHwChannelNum) || + (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + } + + // trust channel information brought by IE + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } + else { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + // 5G Band + else { + if(ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { + // Receive Beacon/ProbeResp frame from adjacent channel. + if ((ucIeHtChannelNum == ucHwChannelNum) || + (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + } + + // trust channel information brought by IE + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } + else { + /* Always update RCPI */ + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + } + + + //4 <5> PHY type setting + prBssDesc->ucPhyTypeSet = 0; + + if (BAND_2G4 == prBssDesc->eBand) { + /* check if support 11n */ + if (prBssDesc->fgIsHTPresent) { + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + } + + /* if not 11n only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* check if support 11g */ + if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) || + prBssDesc->fgIsERPPresent) { + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + } + + /* if not 11g only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) { + /* check if support 11b */ + if ((prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)) { + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + } + } + } + } + else { /* (BAND_5G == prBssDesc->eBande) */ + /* check if support 11n */ + if (prBssDesc->fgIsHTPresent) { + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + } + + /* if not 11n only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* Support 11a definitely */ + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + + ASSERT(!(prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)); + } + } + + + //4 <6> Update BSS_DESC_T's Last Update TimeStamp. + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + + return prBssDesc; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to scan result for query +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +scanAddScanResult ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN P_SW_RFB_T prSwRfb + ) +{ + P_SCAN_INFO_T prScanInfo; + UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame; + PARAM_MAC_ADDRESS rMacAddr; + PARAM_SSID_T rSsid; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + PARAM_802_11_CONFIG_T rConfiguration; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_8 ucRateLen = 0; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prBssDesc->eBand == BAND_2G4) { + if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) + || prBssDesc->fgIsERPPresent) { + eNetworkType = PARAM_NETWORK_TYPE_OFDM24; + } + else { + eNetworkType = PARAM_NETWORK_TYPE_DS; + } + } + else { + ASSERT(prBssDesc->eBand == BAND_5G); + eNetworkType = PARAM_NETWORK_TYPE_OFDM5; + } + + if(prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* NOTE(Kevin): Not supported by WZC(TBD) */ + return WLAN_STATUS_FAILURE; + } + + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader; + COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = (UINT_32) prWlanBeaconFrame->u2BeaconInterval; + rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; + rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet, + 0, + aucRatesEx, + &ucRateLen); + + /* NOTE(Kevin): Set unused entries, if any, at the end of the array to 0. + * from OID_802_11_BSSID_LIST + */ + for (i = ucRateLen; i < sizeof(aucRatesEx) / sizeof(aucRatesEx[0]) ; i++) { + aucRatesEx[i] = 0; + } + + switch(prBssDesc->eBSSType) { + case BSS_TYPE_IBSS: + eOpMode = NET_TYPE_IBSS; + break; + + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_P2P_DEVICE: + case BSS_TYPE_BOW_DEVICE: + default: + eOpMode = NET_TYPE_INFRA; + break; + } + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8)prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (PUINT_8)((UINT_32)(prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse the content of given Beacon or ProbeResp Frame. +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS if not report this SW_RFB_T to host +* @retval WLAN_STATUS_PENDING if report this SW_RFB_T to host as scan result +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +scanProcessBeaconAndProbeResp ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_BSS_INFO_T prAisBssInfo; + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)NULL; +#if CFG_SLT_SUPPORT + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T)NULL; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + //4 <0> Ignore invalid Beacon Frame + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) { +#ifndef _lint + ASSERT(0); +#endif /* _lint */ + return rStatus; + } + +#if CFG_SLT_SUPPORT + prSltInfo = &prAdapter->rWifiVar.rSltInfo; + + if (prSltInfo->fgIsDUT) { + DBGLOG(P2P, INFO, ("\n\rBCN: RX\n")); + prSltInfo->u4BeaconReceiveCnt++; + return WLAN_STATUS_SUCCESS; + } + else { + return WLAN_STATUS_SUCCESS; + } +#endif + + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader; + + //4 <1> Parse and add into BSS_DESC_T + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + + if (prBssDesc) { + + //4 <1.1> Beacon Change Detection for Connected BSS + if(prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + BOOLEAN fgNeedDisconnect = FALSE; + +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + // <1.1.2> check if supported rate differs + if(prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) { + fgNeedDisconnect = TRUE; + } +#endif + + // <1.1.3> beacon content change detected, disconnect immediately + if(fgNeedDisconnect == TRUE) { + aisBssBeaconTimeout(prAdapter); + } + } + + //4 <1.1> Update AIS_BSS_INFO + if(((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA))) { + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + + /* *not* checking prBssDesc->fgIsConnected anymore, + * due to Linksys AP uses " " as hidden SSID, and would have different BSS descriptor */ + if ((!prAisBssInfo->ucDTIMPeriod) && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && + (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { + + prAisBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + + /* sync with firmware for beacon information */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + } + +#if CFG_SUPPORT_ADHOC + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen) && + (prBssDesc->eBSSType == BSS_TYPE_IBSS) && + (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { + + ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, prSwRfb->prHifRxHdr->ucRcpi); + } +#endif /* CFG_SUPPORT_ADHOC */ + } + + rlmProcessBcn(prAdapter, + prSwRfb, + ((P_WLAN_BEACON_FRAME_T)(prSwRfb->pvHeader))->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16)(OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]))); + + //4 <3> Send SW_RFB_T to HIF when we perform SCAN for HOST + if(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE + || prBssDesc->eBSSType == BSS_TYPE_IBSS) { + /* for AIS, send to host */ + if (prConnSettings->fgIsScanReqIssued && + rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { + ENUM_BAND_T eBand; + UINT_8 ucChannel; + BOOLEAN fgAddToScanResult; + + /* check ucChannelNum/eBand for adjacement channel filtering */ + if(cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } + else { + fgAddToScanResult = TRUE; + } + + if(fgAddToScanResult == TRUE) { + rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); + } + } + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + scanP2pProcessBeaconAndProbeResp( + prAdapter, + prSwRfb, + &rStatus, + prBssDesc, + prWlanBeaconFrame); + } +#endif + } + + return rStatus; + +} /* end of scanProcessBeaconAndProbeResp() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or +* MERGE(AdHoc) according to current Connection Policy. +* +* \return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByPolicy ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_SCAN_INFO_T prScanInfo; + + P_LINK_T prBSSDescList; + + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL; + P_BSS_DESC_T prPrimaryBssDesc = (P_BSS_DESC_T)NULL; + P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T)NULL; + + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + P_STA_RECORD_T prPrimaryStaRec; + P_STA_RECORD_T prCandidateStaRec = (P_STA_RECORD_T)NULL; + + OS_SYSTIME rCurrentTime; + + /* The first one reach the check point will be our candidate */ + BOOLEAN fgIsFindFirst = (BOOLEAN)FALSE; + + BOOLEAN fgIsFindBestRSSI = (BOOLEAN)FALSE; + BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN)FALSE; + //BOOLEAN fgIsFindMinChannelLoad = (BOOLEAN)FALSE; + + /* TODO(Kevin): Support Min Channel Load */ + //UINT_8 aucChannelLoad[CHANNEL_NUM] = {0}; + + BOOLEAN fgIsFixedChannel; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if(eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); + } + else { + fgIsFixedChannel = FALSE; + } + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) { + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; + } +#endif + + DBGLOG(SCN, INFO, ("SEARCH: Num Of BSS_DESC_T = %d, Look for SSID: %s\n", + prBSSDescList->u4NumElem, prConnSettings->aucSSID)); + + + //4 <1> The outer loop to search for a candidate. + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* TODO(Kevin): Update Minimum Channel Load Information here */ + + DBGLOG(SCN, INFO, ("SEARCH: ["MACSTR"], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID)); + + + //4 <2> Check PHY Type and attributes + //4 <2.1> Check Unsupported BSS PHY Type + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + + DBGLOG(SCN, INFO, ("SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", + prBssDesc->ucPhyTypeSet)); + continue; + } + + //4 <2.2> Check if has unknown NonHT BSS Basic Rate Set. + if (prBssDesc->fgIsUnknownBssBasicRate) { + + continue; + } + + //4 <2.3> Check if fixed operation cases should be aware + if (fgIsFixedChannel == TRUE && + (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) { + continue; + } + + //4 <2.4> Check if the channel is legal under regulatory domain + if(rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) { + continue; + } + + //4 <2.5> Check if this BSS_DESC_T is stale + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC)) ) { + + continue; + } + + //4 <3> Check if reach the excessive join retry limit + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, + prBssDesc->aucSrcAddr); + + if (prStaRec) { + /* NOTE(Kevin): + * The Status Code is the result of a Previous Connection Request, we use this as SCORE for choosing a proper + * candidate (Also used for compare see <6>) + * The Reason Code is an indication of the reason why AP reject us, we use this Code for "Reject" + * a SCAN result to become our candidate(Like a blacklist). + */ +#if 0 /* TODO(Kevin): */ + if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + DBGLOG(SCN, INFO, ("SEARCH: Ignore BSS with previous Reason Code = %d\n", + prStaRec->u2ReasonCode)); + continue; + } + else +#endif + if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + /* NOTE(Kevin): greedy association - after timeout, we'll still + * try to associate to the AP whose STATUS of conection attempt + * was not success. + * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for + * time bound. + */ + if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || + (CHECK_FOR_TIMEOUT(rCurrentTime, + prStaRec->rLastJoinTime, + SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { + + /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry + * JOIN_MAX_RETRY_FAILURE_COUNT times. + */ + if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) { + prStaRec->ucJoinFailureCount = 0; + } + DBGLOG(SCN, INFO, ("SEARCH: Try to join BSS again which has Status Code = %d (Curr = %ld/Last Join = %ld)\n", + prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime)); + } + else { + DBGLOG(SCN, INFO, ("SEARCH: Ignore BSS which reach maximum Join Retry Count = %d \n", + JOIN_MAX_RETRY_FAILURE_COUNT)); + continue; + } + + } + } + + + //4 <4> Check for various NETWORK conditions + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + + //4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting + /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */ + if (((prConnSettings->eOPMode == NET_TYPE_INFRA) && + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) || + ((prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) && + (prBssDesc->eBSSType != BSS_TYPE_IBSS))) { + + DBGLOG(SCN, INFO, ("SEARCH: Ignore eBSSType = %s\n", + ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) ? + "INFRASTRUCTURE" : "IBSS"))); + continue; + } + + //4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set. + if ((prConnSettings->fgIsConnByBssidIssued) && + (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) { + + if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, INFO, ("SEARCH: Ignore due to BSSID was not matched!\n")); + continue; + } + } + +#if CFG_SUPPORT_ADHOC + //4 <4.3> Check for AdHoc Mode + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + //4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCN, LOUD, ("SEARCH: Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n", + MAC2STR(prBssDesc->aucBSSID))); + continue; + } + + //4 <4.3.2> Check Peer's capability + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + + DBGLOG(SCN, INFO, + ("SEARCH: Ignore BSS DESC MAC: "MACSTR", Capability is not supported for current AdHoc Mode.\n", + MAC2STR(prPrimaryBssDesc->aucBSSID))); + + continue; + } + + + //4 <4.3.3> Compare TSF + if (prBssInfo->fgIsBeaconActivated && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, LOUD, + ("SEARCH: prBssDesc->fgIsLargerTSF = %d\n", + prBssDesc->fgIsLargerTSF)); + + if (!prBssDesc->fgIsLargerTSF) { + DBGLOG(SCN, INFO, + ("SEARCH: Ignore BSS DESC MAC: ["MACSTR"], Smaller TSF\n", MAC2STR(prBssDesc->aucBSSID))); + continue; + } + } + } +#endif /* CFG_SUPPORT_ADHOC */ + + } + + + + +#if 0 /* TODO(Kevin): For IBSS */ + //4 <2.c> Check if this SCAN record has been updated recently for IBSS. + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, ("Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n", + MAC2STR(prBssDesc->aucBSSID))); + continue; + } + } + + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) && + (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, ("Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n", + MAC2STR(prBssDesc->aucBSSID))); + continue; + } + } + + + //4 <4B> Check for IBSS AdHoc Mode. + /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */ + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) { + //4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode. + if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) { + + DBGLOG(SCAN, TRACE, + ("Ignore BSS DESC MAC: "MACSTR", Capability is not supported for current AdHoc Mode.\n", + MAC2STR(prPrimaryBssDesc->aucBSSID))); + + continue; + } + + + //4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE. + if (prAdapter->fgIsIBSSActive && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) { + + if (!fgIsLocalTSFRead) { + NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf); + + DBGLOG(SCAN, TRACE, + ("\n\nCurrent TSF : %08lx-%08lx\n\n", + rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart)); + } + + if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) { + DBGLOG(SCAN, TRACE, + ("Ignore BSS DESC MAC: ["MACSTR"], Current BSSID: ["MACSTR"].\n", + MAC2STR(prPrimaryBssDesc->aucBSSID), MAC2STR(prBssInfo->aucBSSID))); + + DBGLOG(SCAN, TRACE, + ("\n\nBSS's TSF : %08lx-%08lx\n\n", + prPrimaryBssDesc->u8TimeStamp.u.HighPart, prPrimaryBssDesc->u8TimeStamp.u.LowPart)); + + prPrimaryBssDesc->fgIsLargerTSF = FALSE; + continue; + } + else { + prPrimaryBssDesc->fgIsLargerTSF = TRUE; + } + + } + } + + //4 <5> Check the Encryption Status. + if (rsnPerformPolicySelection(prPrimaryBssDesc)) { + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + } + else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } + + /* For RSN Pre-authentication, update the PMKID canidate list for + same SSID and encrypt status */ + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) { + prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate(); + } + } + +#endif + + + prPrimaryBssDesc = (P_BSS_DESC_T)NULL; + + //4 <6> Check current Connection Policy. + switch (prConnSettings->eConnectionPolicy) { + case CONNECT_BY_SSID_BEST_RSSI: + /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */ + if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): following if () statement means that + * If Target is hidden, then we won't connect when user specify SSID_ANY policy. + */ + if (prConnSettings->ucSSIDLen) { + prPrimaryBssDesc = prBssDesc; + + fgIsFindBestRSSI = TRUE; + } + + } + else if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen)) { + prPrimaryBssDesc = prBssDesc; + + fgIsFindBestRSSI = TRUE; + } + break; + + case CONNECT_BY_SSID_ANY: + /* NOTE(Kevin): In this policy, we don't know the desired + * SSID from user, so we should exclude the Hidden SSID from scan list. + * And because we refuse to connect to Hidden SSID node at the beginning, so + * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE, + * then the Connection Settings must be valid without doubt. + */ + if (!prBssDesc->fgIsHiddenSSID) { + prPrimaryBssDesc = prBssDesc; + + fgIsFindFirst = TRUE; + } + break; + + case CONNECT_BY_BSSID: + if(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) { + prPrimaryBssDesc = prBssDesc; + } + break; + + default: + break; + } + + + /* Primary Candidate was not found */ + if (prPrimaryBssDesc == NULL) { + continue; + } + + //4 <7> Check the Encryption Status. + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + fgIsFindFirst = TRUE; + } + else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } + } + else +#endif +#if CFG_RSN_MIGRATION + if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) { + DBGLOG(RSN, INFO, ("Skip while at counter measure period!!!\n")); + continue; + } + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + +#if 0 + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAisSpecBssInfo->u4PmkidCandicateCount) { + if (rsnCheckPmkidCandicate()) { + DBGLOG(RSN, WARN, ("Prepare a timer to indicate candidate "MACSTR"\n", + MAC2STR(prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.aucBssid))); + cnmTimerStopTimer(&prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(&prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } +#endif + } + else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } +#endif + } + else { + /* Todo:: P2P and BOW Policy Selection */ + } + + prPrimaryStaRec = prStaRec; + + //4 <8> Compare the Candidate and the Primary Scan Record. + if (!prCandidateBssDesc) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + + //4 <8.1> Condition - Get the first matched one. + if (fgIsFindFirst) { + break; + } + } + else { +#if 0 /* TODO(Kevin): For security(TBD) */ + //4 <6B> Condition - Choose the one with best Encryption Score. + if (fgIsFindBestEncryptionLevel) { + if (prCandidateBssDesc->ucEncLevel < + prPrimaryBssDesc->ucEncLevel) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + + /* If reach here, that means they have the same Encryption Score. + */ + + //4 <6C> Condition - Give opportunity to the one we didn't connect before. + // For roaming, only compare the candidates other than current associated BSSID. + if (!prCandidateBssDesc->fgIsConnected && !prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateStaRec != (P_STA_RECORD_T)NULL) && + (prCandidateStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + + DBGLOG(SCAN, TRACE, ("So far -BSS DESC MAC: "MACSTR" has nonzero Status Code = %d\n", + MAC2STR(prCandidateBssDesc->aucBSSID), prCandidateStaRec->u2StatusCode)); + + if (prPrimaryStaRec != (P_STA_RECORD_T)NULL) { + if (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + + /* Give opportunity to the one with smaller rLastJoinTime */ + if (TIME_BEFORE(prCandidateStaRec->rLastJoinTime, + prPrimaryStaRec->rLastJoinTime)) { + continue; + } + /* We've connect to CANDIDATE recently, let us try PRIMARY now */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY's u2StatusCode = 0 */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY has no StaRec - We didn't connet to PRIMARY before */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + else { + if ((prPrimaryStaRec != (P_STA_RECORD_T)NULL) && + (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + continue; + } + } + } +#endif + + + //4 <6D> Condition - Visible SSID win Hidden SSID. + if (prCandidateBssDesc->fgIsHiddenSSID) { + if (!prPrimaryBssDesc->fgIsHiddenSSID) { + prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */ + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + else { + if (prPrimaryBssDesc->fgIsHiddenSSID) { + continue; + } + } + + + //4 <6E> Condition - Choose the one with better RCPI(RSSI). + if (fgIsFindBestRSSI) { + /* TODO(Kevin): We shouldn't compare the actual value, we should + * allow some acceptable tolerance of some RSSI percentage here. + */ + DBGLOG(SCN, TRACE, ("Candidate ["MACSTR"]: RCPI = %d, Primary ["MACSTR"]: RCPI = %d\n", + MAC2STR(prCandidateBssDesc->aucBSSID), prCandidateBssDesc->ucRCPI, + MAC2STR(prPrimaryBssDesc->aucBSSID), prPrimaryBssDesc->ucRCPI)); + + ASSERT(!(prCandidateBssDesc->fgIsConnected && + prPrimaryBssDesc->fgIsConnected)); + + /* NOTE: To prevent SWING, we do roaming only if target AP has at least 5dBm larger than us. */ + if (prCandidateBssDesc->fgIsConnected) { + if (prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= prPrimaryBssDesc->ucRCPI) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + else if (prPrimaryBssDesc->fgIsConnected) { + if (prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + else if (prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + +#if 0 + /* If reach here, that means they have the same Encryption Score, and + * both RSSI value are close too. + */ + //4 <6F> Seek the minimum Channel Load for less interference. + if (fgIsFindMinChannelLoad) { + + /* TODO(Kevin): Check which one has minimum channel load in its channel */ + } +#endif + } + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c new file mode 100755 index 000000000000..2fc9b8bac204 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c @@ -0,0 +1,1109 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#1 $ +*/ + +/*! \file "scan_fsm.c" + \brief This file defines the state transition function for SCAN FSM. + + The SCAN FSM is part of SCAN MODULE and responsible for performing basic SCAN + behavior as metioned in IEEE 802.11 2007 11.1.3.1 & 11.1.3.2 . +*/ + + + +/* +** $Log: scan_fsm.c $ + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 14 2011 yuche.tsai + * [WCXRP00001095] [Volunteer Patch][Driver] Always Scan before enable Hot-Spot. + * Fix bug when unregister P2P network.. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * free mailbox message afte parsing is completed. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cp.wu + * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning + * surpress klock warning with code path rewritten + * + * 03 18 2011 cm.chang + * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command + * As CR title + * + * 02 18 2011 yuche.tsai + * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame during search phase do not contain P2P wildcard SSID. + * Take P2P wildcard SSID into consideration. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix scan channel extension issue when p2p module is not registered. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 16 2010 yuche.tsai + * NULL + * Fix bug for processing queued scan request. + * + * 08 11 2010 yuche.tsai + * NULL + * Add a function for returning channel. + * + * 08 05 2010 yuche.tsai + * NULL + * Update SCAN FSM for support P2P Device discovery scan. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 26 2010 yuche.tsai + * + * Add option of channel extension while cancelling scan request. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 20 2010 cp.wu + * + * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. + * + * 07 19 2010 cp.wu + * + * due to FW/DRV won't be sync. precisely, some strict assertions should be eased. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * when returning to SCAN_IDLE state, send a correct message to source FSM. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine the order of Stop TX Queue and Switch Channel + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update pause/resume/flush API to new Bitmap API + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Ignore the PROBE_DELAY state if the value of Probe Delay == 0 + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add set RX Filter to receive BCN from different BSSID during SCAN + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove flag of CFG_TEST_MGMT_FSM + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Change parameter of scanSendProbeReqFrames() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update scnFsmSteps() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = { + (PUINT_8)DISP_STRING("SCAN_STATE_IDLE"), + (PUINT_8)DISP_STRING("SCAN_STATE_SCANNING"), +}; +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN ENUM_SCAN_STATE_T eNextState + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prMsgHdr; + + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + do { + +#if DBG + DBGLOG(SCN, STATE, ("TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], + apucDebugScanState[eNextState])); +#else + DBGLOG(SCN, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n", + DBG_SCN_IDX, + prScanInfo->eCurrentState, + eNextState)); +#endif + + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prScanInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN)FALSE; + + switch (prScanInfo->eCurrentState) { + case SCAN_STATE_IDLE: + /* check for pending scanning requests */ + if(!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { + // load next message from pending list as scan parameters + LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), prMsgHdr, P_MSG_HDR_T); + + if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ)prMsgHdr); + } + else { + scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2)prMsgHdr); + } + + /* switch to next state */ + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + + cnmMemFree(prAdapter, prMsgHdr); + } + break; + + case SCAN_STATE_SCANNING: + if(prScanParam->fgIsScanV2 == FALSE) { + scnSendScanReq(prAdapter); + } + else { + scnSendScanReqV2(prAdapter); + } + break; + + default: + ASSERT(0); + break; + + } + } + while (fgIsTransition); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnSendScanReq ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_REQ rCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + // send command packet for scan + kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ)); + + rCmdScanReq.ucSeqNum = prScanParam->ucSeqNum; + rCmdScanReq.ucNetworkType = (UINT_8)prScanParam->eNetTypeIndex; + rCmdScanReq.ucScanType = (UINT_8)prScanParam->eScanType; + rCmdScanReq.ucSSIDType = prScanParam->ucSSIDType; + + if(prScanParam->ucSSIDNum == 1) { + COPY_SSID(rCmdScanReq.aucSSID, + rCmdScanReq.ucSSIDLength, + prScanParam->aucSpecifiedSSID[0], + prScanParam->ucSpecifiedSSIDLen[0]); + } + + rCmdScanReq.ucChannelType = (UINT_8)prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + rCmdScanReq.ucChannelListNum = prScanParam->ucChannelListNum; + + for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) { + rCmdScanReq.arChannelList[i].ucBand = + (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + rCmdScanReq.arChannelList[i].ucChannelNum = + (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum; + } + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; + } +#endif + + if(prScanParam->u2IELen <= MAX_IE_LENGTH) { + rCmdScanReq.u2IELen = prScanParam->u2IELen; + } + else { + rCmdScanReq.u2IELen = MAX_IE_LENGTH; + } + + if (prScanParam->u2IELen) { + kalMemCopy(rCmdScanReq.aucIE, + prScanParam->aucIE, + sizeof(UINT_8) * rCmdScanReq.u2IELen); + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ, aucIE) + rCmdScanReq.u2IELen, + (PUINT_8)&rCmdScanReq, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V2 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnSendScanReqV2 ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_REQ_V2 rCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + // send command packet for scan + kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ_V2)); + + rCmdScanReq.ucSeqNum = prScanParam->ucSeqNum; + rCmdScanReq.ucNetworkType = (UINT_8)prScanParam->eNetTypeIndex; + rCmdScanReq.ucScanType = (UINT_8)prScanParam->eScanType; + rCmdScanReq.ucSSIDType = prScanParam->ucSSIDType; + + for (i = 0 ; i < prScanParam->ucSSIDNum; i++) { + COPY_SSID(rCmdScanReq.arSSID[i].aucSsid, + rCmdScanReq.arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i]); + } + + rCmdScanReq.u2ProbeDelayTime = (UINT_8)prScanParam->u2ProbeDelayTime; + rCmdScanReq.ucChannelType = (UINT_8)prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + rCmdScanReq.ucChannelListNum = prScanParam->ucChannelListNum; + + for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) { + rCmdScanReq.arChannelList[i].ucBand = + (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + rCmdScanReq.arChannelList[i].ucChannelNum = + (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum; + } + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; + } +#endif + + if(prScanParam->u2IELen <= MAX_IE_LENGTH) { + rCmdScanReq.u2IELen = prScanParam->u2IELen; + } + else { + rCmdScanReq.u2IELen = MAX_IE_LENGTH; + } + + if (prScanParam->u2IELen) { + kalMemCopy(rCmdScanReq.aucIE, + prScanParam->aucIE, + sizeof(UINT_8) * rCmdScanReq.u2IELen); + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_V2, aucIE) + rCmdScanReq.u2IELen, + (PUINT_8)&rCmdScanReq, + NULL, + 0); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmMsgStart ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + + ASSERT(prMsgHdr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + + if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) { + if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ)prMsgHdr); + } + else if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2)prMsgHdr); + } + else { + // should not deliver to this function + ASSERT(0); + } + + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); + } + else { + LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, &prMsgHdr->rLinkEntry); + } + + return; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmMsgAbort ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancel; + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_CANCEL rCmdScanCancel; + + ASSERT(prMsgHdr); + + prScanCancel = (P_MSG_SCN_SCAN_CANCEL)prMsgHdr; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if(prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucNetTypeIndex == (UINT_8)prScanParam->eNetTypeIndex) { + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + +#if CFG_ENABLE_WIFI_DIRECT + if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt; + } + else { + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; + } +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SCAN_CANCEL), + (PUINT_8)&rCmdScanCancel, + NULL, + 0); + + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, + (UINT_8)prScanParam->eNetTypeIndex, + SCAN_STATUS_CANCELLED); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } + else { + scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucNetTypeIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing (Legacy) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmHandleScanMsg ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_SCN_SCAN_REQ prScanReqMsg + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T)prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + if (prScanParam->ucSSIDType & (SCAN_REQ_SSID_SPECIFIED | SCAN_REQ_SSID_P2P_WILDCARD)) { + prScanParam->ucSSIDNum = 1; + + COPY_SSID(prScanParam->aucSpecifiedSSID[0], + prScanParam->ucSpecifiedSSIDLen[0], + prScanReqMsg->aucSSID, + prScanReqMsg->ucSSIDLength); + + // reset SSID length to zero for rest array entries + for(i = 1 ; i < SCN_SSID_MAX_NUM ; i++) { + prScanParam->ucSpecifiedSSIDLen[i] = 0; + } + } + else { + prScanParam->ucSSIDNum = 0; + + for(i = 0 ; i < SCN_SSID_MAX_NUM ; i++) { + prScanParam->ucSpecifiedSSIDLen[i] = 0; + } + } + + prScanParam->u2ProbeDelayTime = 0; + prScanParam->eScanChannel = prScanReqMsg->eScanChannel; + if(prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if(prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) { + prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; + } + else { + prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + kalMemCopy(prScanParam->arChnlInfoList, + prScanReqMsg->arChnlInfoList, + sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); + } + + if(prScanReqMsg->u2IELen <= MAX_IE_LENGTH) { + prScanParam->u2IELen = prScanReqMsg->u2IELen; + } + else { + prScanParam->u2IELen = MAX_IE_LENGTH; + } + + if(prScanParam->u2IELen) { + kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; + } +#endif + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if(prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) { + prScanParam->fgIsObssScan = TRUE; + } + else { + prScanParam->fgIsObssScan = FALSE; + } + + prScanParam->fgIsScanV2 = FALSE; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing - V2 with multiple SSID support +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmHandleScanMsgV2 ( + IN P_ADAPTER_T prAdapter, + IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T)prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; + + for(i = 0 ; i < prScanReqMsg->ucSSIDNum ; i++) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], + prScanReqMsg->prSsid[i].aucSsid, + (UINT_8)prScanReqMsg->prSsid[i].u4SsidLen); + } + + prScanParam->u2ProbeDelayTime = prScanReqMsg->u2ProbeDelay; + prScanParam->eScanChannel = prScanReqMsg->eScanChannel; + if(prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if(prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) { + prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; + } + else { + prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + kalMemCopy(prScanParam->arChnlInfoList, + prScanReqMsg->arChnlInfoList, + sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); + } + + if(prScanReqMsg->u2IELen <= MAX_IE_LENGTH) { + prScanParam->u2IELen = prScanReqMsg->u2IELen; + } + else { + prScanParam->u2IELen = MAX_IE_LENGTH; + } + + if(prScanParam->u2IELen) { + kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; + } +#endif + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if(prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) { + prScanParam->fgIsObssScan = TRUE; + } + else { + prScanParam->fgIsObssScan = FALSE; + } + + prScanParam->fgIsScanV2 = TRUE; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Remove pending scan request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmRemovePendingMsg ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, + IN UINT_8 ucNetTypeIndex + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL; + P_LINK_ENTRY_T prRemoveLinkEntry = NULL; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* traverse through rPendingMsgList for removal */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, + prPendingMsgHdrNext, + &(prScanInfo->rPendingMsgList), + rLinkEntry, + MSG_HDR_T) { + if(prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + P_MSG_SCN_SCAN_REQ prScanReqMsg = (P_MSG_SCN_SCAN_REQ)prPendingMsgHdr; + + if(ucSeqNum == prScanReqMsg->ucSeqNum && + ucNetTypeIndex == prScanReqMsg->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } + else if(prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + P_MSG_SCN_SCAN_REQ_V2 prScanReqMsgV2 = (P_MSG_SCN_SCAN_REQ_V2)prPendingMsgHdr; + + if(ucSeqNum == prScanReqMsgV2->ucSeqNum && + ucNetTypeIndex == prScanReqMsgV2->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } + + if(prRemoveLinkEntry) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + ucSeqNum, + ucNetTypeIndex, + SCAN_STATUS_CANCELLED); + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnEventScanDone ( + IN P_ADAPTER_T prAdapter, + IN P_EVENT_SCAN_DONE prScanDone + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + // buffer empty channel information + if(prScanParam->eScanChannel == SCAN_CHANNEL_FULL + || prScanParam->eScanChannel == SCAN_CHANNEL_2G4) { + if(prScanDone->ucSparseChannelValid) { + prScanInfo->fgIsSparseChannelValid = TRUE; + prScanInfo->rSparseChannel.eBand = (ENUM_BAND_T)prScanDone->rSparseChannel.ucBand; + prScanInfo->rSparseChannel.ucChannelNum = prScanDone->rSparseChannel.ucChannelNum; + } + else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + } + + if(prScanInfo->eCurrentState == SCAN_STATE_SCANNING && + prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, + (UINT_8)prScanParam->eNetTypeIndex, + SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } + else { + DBGLOG(SCN, LOUD, ("Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, + prScanInfo->eCurrentState)); + } + + return; +} /* end of scnEventScanDone */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, + IN UINT_8 ucNetTypeIndex, + IN ENUM_SCAN_STATUS eScanStatus + ) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_DONE)); + if (!prScanDoneMsg) { + ASSERT(0); // Can't indicate SCAN FSM Complete + return; + } + + if(prScanParam->fgIsObssScan == TRUE) { + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE; + } + else { + switch((ENUM_NETWORK_TYPE_INDEX_T)ucNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; +#endif + + default: + DBGLOG(SCN, LOUD, ("Unexpected Network Type: %d\n", ucNetTypeIndex)); + ASSERT(0); + break; + } + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucNetTypeIndex = ucNetTypeIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prScanDoneMsg, + MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Query for most sparse channel +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnQuerySparseChannel ( + IN P_ADAPTER_T prAdapter, + P_ENUM_BAND_T prSparseBand, + PUINT_8 pucSparseChannel + ) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if(prScanInfo->fgIsSparseChannelValid == TRUE) { + if(prSparseBand) { + *prSparseBand = prScanInfo->rSparseChannel.eBand; + } + + if(pucSparseChannel) { + *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum; + } + + return TRUE; + } + else { + return FALSE; + } +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c new file mode 100755 index 000000000000..862b9fa64661 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c @@ -0,0 +1,1255 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/sec_fsm.c#1 $ +*/ + +/*! \file "sec_fsm.c" + \brief This is the file implement security check state machine. + + In security module, do the port control check after success join to an AP, + and the path to NORMAL TR, the state machine handle these state transition. +*/ + + + +/* +** $Log: sec_fsm.c $ + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 03 29 2011 wh.su + * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error + * fixed the kclocwork error. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 19 2010 wh.su + * + * fixed the compilng error at debug mode. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 13 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the Klocwork error and refine the class error message. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 13 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * fixed the compiling warning + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine some code + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine the code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * code refine + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function name + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the state machine, to meet the firmware security design v1.1 + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_RSN_MIGRATION + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugSecState[SEC_STATE_NUM] = { + (PUINT_8)DISP_STRING("SEC_STATE_INIT"), + (PUINT_8)DISP_STRING("SEC_STATE_INITIATOR_PORT_BLOCKED"), + (PUINT_8)DISP_STRING("SEC_STATE_RESPONDER_PORT_BLOCKED"), + (PUINT_8)DISP_STRING("SEC_STATE_CHECK_OK"), + (PUINT_8)DISP_STRING("SEC_STATE_SEND_EAPOL"), + (PUINT_8)DISP_STRING("SEC_STATE_SEND_DEAUTH"), + (PUINT_8)DISP_STRING("SEC_STATE_COUNTERMEASURE"), +}; +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmInit ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + + #if 1 /* MT6620 */ + //At MT5921, is ok, but at MT6620, firmware base ASIC, the firmware + //will lost these data, thus, driver have to keep the wep material and + //setting to firmware while awake from D3. + #endif + + prSecInfo->eCurrentState = SEC_STATE_INIT; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + if (IS_STA_IN_AIS(prSta)) { + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prAisSpecBssInfo->u4RsnaLastMICFailTime = 0; + prAisSpecBssInfo->fgCheckEAPoLTxDone = FALSE; + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC)secFsmEventEapolTxTimeout, + (UINT_32)prSta); + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + (PFN_MGMT_TIMEOUT_FUNC)secFsmEventEndOfCounterMeasure, + (UINT_32)prSta); + + } + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do uninitialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID /* whsu:Todo: */ +secFsmUnInit ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + //nicPrivacyRemoveWlanTable(prSta->ucWTEntry); + + if (IS_STA_IN_AIS(prSta)) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer); + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* STANDBY to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_INIT_to_CHECK_OK ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to INITIATOR_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_INIT_to_INITIATOR_PORT_BLOCKED ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to RESPONDER_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_INIT_to_RESPONDER_PORT_BLOCKED ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INITIATOR_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_INITIATOR_PORT_BLOCKED_to_CHECK_OK ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* RESPONDER_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_RESPONDER_PORT_BLOCKED_to_CHECK_OK ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* CHECK_OK to SEND_EAPOL +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_CHECK_OK_to_SEND_EAPOL ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + ASSERT(prSta); + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + prAisBssInfo->fgCheckEAPoLTxDone = TRUE; + + //cnmTimerStartTimer(prAdapter, + // &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer, + // SEC_TO_MSEC(EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC)); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_EAPOL to SEND_DEAUTH. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_SEND_EAPOL_to_SEND_DEAUTH ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + /* Compose deauth frame to AP, a call back function for tx done */ + if (authSendDeauthFrame(prAdapter, + prSta, + (P_SW_RFB_T)NULL, + REASON_CODE_MIC_FAILURE, + (PFN_TX_DONE_HANDLER)secFsmEventDeauthTxDone) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_SEND_DEAUTH_to_COUNTERMEASURE ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + ASSERT(prAdapter); + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + //Start the 60 sec timer + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + SEC_TO_MSEC(COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC)); + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +__KAL_INLINE__ VOID +secFsmTrans_COUNTERMEASURE_to_INIT ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + + //Clear the counter measure flag + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The Core FSM engine of security module. +* +* \param[in] prSta Pointer to the Sta record +* \param[in] eNextState Enum value of next sec STATE +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmSteps ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta, + IN ENUM_SEC_STATE_T eNextState + ) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + ASSERT(prSecInfo); + + DEBUGFUNC("secFsmSteps"); + do { + /* Do entering Next State */ + prSecInfo->ePreviousState = prSecInfo->eCurrentState; + + /* Do entering Next State */ +#if DBG + DBGLOG(RSN, STATE, ("\n"MACSTR" TRANSITION: [%s] -> [%s]\n\n", + MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState], + apucDebugSecState[eNextState])); +#else + DBGLOG(RSN, STATE, ("\n"MACSTR" [%d] TRANSITION: [%d] -> [%d]\n\n", + MAC2STR(prSta->aucMacAddr), + DBG_RSN_IDX, + prSecInfo->eCurrentState, + eNextState)); +#endif + prSecInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN)FALSE; +#if 0 + /* Do tasks of the State that we just entered */ + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + break; + case SEC_STATE_INITIATOR_PORT_BLOCKED: + break; + case SEC_STATE_RESPONDER_PORT_BLOCKED: + break; + case SEC_STATE_CHECK_OK: + break; + case SEC_STATE_SEND_EAPOL: + break; + case SEC_STATE_SEND_DEAUTH: + break; + case SEC_STATE_COUNTERMEASURE: + break; + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + } +#endif + } + while (fgIsTransition); + + return; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventStart ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + ENUM_SEC_STATE_T eNextState; + + DBGLOG(RSN, TRACE, ("secFsmRunEventStart\n")); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + DBGLOG(RSN, TRACE, ("secFsmRunEventStart for sta "MACSTR" network %d\n", + MAC2STR(prSta->aucMacAddr), prSta->ucNetTypeIndex)); + + prSecInfo = (P_SEC_INFO_T)&prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + //prSta->fgTransmitKeyExist = FALSE; + //whsu:: nicPrivacySetStaDefaultWTIdx(prSta); + +#if 1 /* Since the 1x and key can set to firmware in order, always enter the check ok state */ + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); +#else + if (IS_STA_IN_AIS(prSta->eStaType)) { + if (secRsnKeyHandshakeEnabled(prAdapter) == TRUE +#if CFG_SUPPORT_WAPI + || (prAdapter->rWifiVar.rConnSettings.fgWapiMode) +#endif + ) { + prSta->fgTransmitKeyExist = FALSE; + //nicPrivacyInitialize(prSta->ucNetTypeIndex); + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); + } + else { + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); + } + } +#if CFG_ENABLE_WIFI_DIRECT || CFG_ENABLE_BT_OVER_WIFI + #if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_BT_OVER_WIFI + else if ((prSta->eStaType == STA_TYPE_BOW_CLIENT) || + (prSta->eStaType == STA_TYPE_P2P_GC)) + #elif CFG_ENABLE_WIFI_DIRECT + else if (prSta->eStaType == STA_TYPE_P2P_GC) + #elif CFG_ENABLE_BT_OVER_WIFI + else if (prSta->eStaType == STA_TYPE_BOW_CLIENT) + #endif + { + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, RESPONDER_PORT_BLOCKED); + } +#endif + else { + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); + } +#endif + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return; +} /* secFsmRunEventStart */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function called by reset procedure to force the sec fsm enter +* idle state +* +* \param[in] ucNetTypeIdx The Specific Network type index +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventAbort ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + + DBGLOG(RSN, TRACE, ("secFsmEventAbort for sta "MACSTR" network %d\n", + MAC2STR(prSta->aucMacAddr), prSta->ucNetTypeIndex)); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + prSecInfo = (P_SEC_INFO_T)&prSta->rSecInfo; + + prSta->fgTransmitKeyExist = FALSE; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + if (prSecInfo == NULL) + return; + + if (IS_STA_IN_AIS(prSta)) { + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + if (prSecInfo->eCurrentState == SEC_STATE_SEND_EAPOL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone == FALSE) { + DBGLOG(RSN, TRACE, ("EAPOL STATE not match the flag\n")); + //cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); + } + } + } + prSecInfo->eCurrentState = SEC_STATE_INIT; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "2nd EAPoL Tx is sending" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEvent2ndEapolTx ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + //BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + DEBUGFUNC("secFsmRunEvent2ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR" Sec state %s\n", MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR" Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED : + case SEC_STATE_CHECK_OK : + prSecInfo->fg2nd1xSend = TRUE; + break; + default: +#if DBG + DBGLOG(RSN, WARN, ("Rcv 2nd EAPoL at %s\n", apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, WARN, ("Rcv 2nd EAPoL at [%d]\n", prSecInfo->eCurrentState)); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return; + +}/* secFsmRunEvent2ndEapolTx */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "4th EAPoL Tx is Tx done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEvent4ndEapolTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + P_CMD_802_11_KEY prStoredKey; + + DEBUGFUNC("secFsmRunEvent4ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED : + case SEC_STATE_CHECK_OK : + prSecInfo->fg2nd1xSend = FALSE; + if (prSecInfo->fgKeyStored) { + prStoredKey = (P_CMD_802_11_KEY)prSecInfo->aucStoredKey; + + //prSta = rxmLookupStaRecIndexFromTA(prStoredKey->aucPeerAddr); + //if (nicPrivacySetKeyEntry(prStoredKey, prSta->ucWTEntry) == FALSE) + // DBGLOG(RSN, WARN, ("nicPrivacySetKeyEntry() fail,..\n")); + + //key update + prSecInfo->fgKeyStored = FALSE; + prSta->fgTransmitKeyExist = TRUE; + } + if (prSecInfo->eCurrentState == SEC_STATE_INITIATOR_PORT_BLOCKED) { + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + } + break; + default: + +#if DBG + DBGLOG(RSN, WARN, ("Rcv thh EAPoL Tx done at %s\n", apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, WARN, ("Rcv thh EAPoL Tx done at [%d]\n", prSecInfo->eCurrentState)); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return; + +}/* secFsmRunEvent4ndEapolTx */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Pairwise key installed" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \retval TRUE The key can be installed to HW +* \retval FALSE The kay conflict with the current key, abort it +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secFsmEventPTKInstalled ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgStatus = TRUE; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + if (prSecInfo == NULL) + return TRUE; /* Not PTK */ + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + eNextState = prSecInfo->eCurrentState; + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + /* Legacy wep, wpa-none */ + break; + + case SEC_STATE_INITIATOR_PORT_BLOCKED: + if (prSecInfo->fg2nd1xSend) { + } + else { + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + } + break; + + case SEC_STATE_RESPONDER_PORT_BLOCKED: + SEC_STATE_TRANSITION(prAdapter, prSta, RESPONDER_PORT_BLOCKED, CHECK_OK); + break; + + + case SEC_STATE_CHECK_OK: + break; + + default: + fgStatus = FALSE; + break; + } + + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return fgStatus; + +} /* end of secFsmRunEventPTKInstalled() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Counter Measure" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventStartCounterMeasure ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prSta + ) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + DEBUGFUNC("secFsmRunEventStartCounterMeasure"); + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + prSecInfo = &prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + prAdapter->rWifiVar.rAisSpecificBssInfo.u4RsnaLastMICFailTime = 0; + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_CHECK_OK: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = TRUE; + + // dls port control + SEC_STATE_TRANSITION(prAdapter, prSta, CHECK_OK, SEND_EAPOL); + } + break; + + default: + break; + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return; + +} /* secFsmRunEventStartCounterMeasure */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "802.1x EAPoL Tx Done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventEapolTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("secFsmRunEventEapolTxDone"); + + ASSERT(prStaRec); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(RSN, INFO, ("Error EAPoL fram fail to send!!\n")); + //ASSERT(0); + return; + } + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + prSecInfo = &prStaRec->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prStaRec->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prStaRec->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_SEND_EAPOL: + if (prAisBssInfo->fgCheckEAPoLTxDone == FALSE) { + ASSERT(0); + } + + prAisBssInfo->fgCheckEAPoLTxDone = FALSE; + //cnmTimerStopTimer(prAdapter, &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer); + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_EAPOL, SEND_DEAUTH); + break; + default: + break; + } + + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prStaRec, eNextState); + } + + return; + +}/* secFsmRunEventEapolTxDone */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Deauth frame Tx Done" to Sec FSM. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventDeauthTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_STA_RECORD_T prStaRec; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + DEBUGFUNC("secFsmRunEventDeauthTxDone"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + ASSERT(prStaRec); + + if (!prStaRec) + return; + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + prSecInfo = (P_SEC_INFO_T)&prStaRec->rSecInfo; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prStaRec->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prStaRec->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + + DBGLOG(RSN, TRACE, ("Set timer %d\n", COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC)); + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_DEAUTH, COUNTERMEASURE); + + break; + + default: + ASSERT(0); + break; + } + + return; +}/* secFsmRunEventDeauthTxDone */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check the eapol error frame fail to send issue. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventEapolTxTimeout ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Parm + ) +{ + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("secFsmRunEventEapolTxTimeout"); + + prStaRec = (P_STA_RECORD_T)u4Parm; + + ASSERT(prStaRec); + + /* Todo:: How to handle the Eapol Error fail to send case? */ + ASSERT(0); + + return; + +}/* secFsmEventEapolTxTimeout */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will stop the counterMeasure duration. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventEndOfCounterMeasure ( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Parm + ) +{ + P_STA_RECORD_T prSta; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN)FALSE; + + DEBUGFUNC("secFsmRunEventEndOfCounterMeasure"); + + prSta = (P_STA_RECORD_T)u4Parm; + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, ("Counter Measure should occur at AIS network!!\n")); + //ASSERT(0); + return; + } + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr), + apucDebugSecState[prSecInfo->eCurrentState])); +#else + DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState)); +#endif + + switch(prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = FALSE; + + SEC_STATE_TRANSITION(prAdapter, prSta, COUNTERMEASURE, INIT); + } + break; + + default: + ASSERT(0); + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) { + secFsmSteps(prAdapter, prSta, eNextState); + } + + return; +}/* end of secFsmRunEventEndOfCounterMeasure */ +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c new file mode 100755 index 000000000000..0a65bb0b579f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c @@ -0,0 +1,1268 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 $ +*/ + +/*! \file "swcr.c" + \brief + +*/ + + + +/* +** $Log: swcr.c $ + * + * 06 04 2012 tsaiyuan.hsu + * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" + * resolve build waring for "WNM_UNIT_TEST not defined". + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 22 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * keep debug counter setting after wake up. + * + * 11 15 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * fix debug counters of rx in driver. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters, eCurPsProf, for PS. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 03 28 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Fix Klockwork warning. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add swcr for test. + * +* +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_SWCR + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if 0 +extern SWCR_MAP_ENTRY_T g_arRlmArSwCrMap[]; +SWCR_MOD_MAP_ENTRY_T g_arSwCrAllMaps[] = { + { SWCR_MAP_NUM(g_arRlmArSwCrMap), g_arRlmArSwCrMap}, /* 0x00nn */ + {0,NULL} +}; +#endif + +VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); +void testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1); +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Support Debug */ +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); +VOID swCrDebugCheckTimeout( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param); +VOID swCrDebugQuery( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ); +VOID swCrDebugQueryTimeout( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo); + +UINT_32 g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +UINT_32 g_u4mDNSRXFilter = 0; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4*/ + +static TIMER_T g_rSwcrDebugTimer; +static BOOLEAN g_fgSwcrDebugTimer = FALSE; +static UINT_32 g_u4SwcrDebugCheckTimeout = 0; +static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType = 0; +static UINT_32 g_u4SwcrDebugFrameDumpType = 0; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define TEST_PS 1 + +const static PFN_CMD_RW_T g_arSwCtrlCmd[] ={ + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0 + , testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ==1) && (WNM_UNIT_TEST ==1) + , testWNMCmdCategory0 +#endif +#endif +}; + + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_MDNS_FILTER, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_MDNS_FILTER_START (1<<31) +#define RX_MDNS_FILTER_IPV4 (1<<2) +#define RX_MDNS_FILTER_IPV6 (1<<3) +typedef enum _ENUM_SWCR_RX_MDNS_FILTER_CMD_T { + SWCR_RX_MDNS_FILTER_CMD_STOP = 0, + SWCR_RX_MDNS_FILTER_CMD_START, + SWCR_RX_MDNS_FILTER_CMD_ADD, + SWCR_RX_MDNS_FILTER_CMD_REMOVE, + SWCR_RX_MDNS_FILTER_NUM +} ENUM_SWCR_RX_MDNS_FILTER_CMD_T; + +#if TEST_PS +enum { + TEST_PS_MAGIC, + TEST_PS_SETUP_BSS, + TEST_PS_ENABLE_BEACON, + TEST_PS_TRIGGER_BMC, + TEST_PS_SEND_NULL, + TEST_PS_BUFFER_BMC, + TEST_PS_UPDATE_BEACON, + TEST_PS_CATA0_INDEX_NUM +}; + +enum { + TEST_PS_STA_PS, + TEST_PS_STA_ENTER_PS, + TEST_PS_STA_EXIT_PS, + TEST_PS_STA_TRIGGER_PSPOLL, + TEST_PS_STA_TRIGGER_FRAME, + TEST_PS_CATA1_INDEX_NUM +}; +#endif + +#if CFG_SUPPORT_802_11V +#if WNM_UNIT_TEST +enum { + TEST_WNM_TIMING_MEAS, + TEST_WNM_CATA0_INDEX_NUM +}; +#endif +#endif + + +#define _SWCTRL_MAGIC 0x66201642 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +void dumpQueue(P_ADAPTER_T prAdapter) +{ + + P_TX_CTRL_T prTxCtrl; + P_QUE_MGT_T prQM; + P_GLUE_INFO_T prGlueInfo; + UINT_32 i; + UINT_32 j; + + + DEBUGFUNC("dumpQueue"); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + + for(i = TC0_INDEX; i<=TC5_INDEX; i++) { + DBGLOG(SW4, INFO,( "TC %u\n",i)); + DBGLOG(SW4, INFO,( "Max %u Free %u\n", + prTxCtrl->rTc.aucMaxNumOfBuffer[i], prTxCtrl->rTc.aucFreeBufferCount[i])); + + DBGLOG(SW4, INFO,("Average %u minReserved %u CurrentTcResource %u GuaranteedTcResource %u\n", + QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], + prQM->au4GuaranteedTcResource[i])); + + } + + + for(i = 0; iau4HeadStaRecIndex[i],prQM->au4ForwardCount[i])); + } + + DBGLOG(SW4, INFO,( "BMC or unknown TxQueue Len %u\n",prQM->arTxQueue[0].u4NumElem)); + DBGLOG(SW4, INFO,( "Pending %d\n",prGlueInfo->i4TxPendingFrameNum)); + DBGLOG(SW4, INFO,( "Pending Security %d\n",prGlueInfo->i4TxPendingSecurityFrameNum)); +#if defined(LINUX) + for(i=0;i<4;i++){ + for(j=0;jai4TxPendingFrameNumPerQueue[i][j])); + } + } +#endif + + DBGLOG(SW4, INFO,( " rFreeSwRfbList %u\n", prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem)); + DBGLOG(SW4, INFO,( " rReceivedRfbList %u\n", prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem)); + DBGLOG(SW4, INFO,( " rIndicatedRfbList %u\n", prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem)); + DBGLOG(SW4, INFO,( " ucNumIndPacket %u\n", prAdapter->rRxCtrl.ucNumIndPacket)); + DBGLOG(SW4, INFO,( " ucNumRetainedPacket %u\n", prAdapter->rRxCtrl.ucNumRetainedPacket)); + + +} + + +void dumpSTA(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + UINT_8 ucWTEntry; + UINT_32 i; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("dumpSTA"); + + ASSERT(prStaRec); + ucWTEntry = prStaRec->ucWTEntry; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(SW4, INFO,("Mac address: " MACSTR " Rcpi %u" "\n", MAC2STR(prStaRec->aucMacAddr),prStaRec->ucRCPI)); + + DBGLOG(SW4, INFO,("Idx %u Wtbl %u Used %u State %u Bss Phy 0x%x Sta DesiredPhy 0x%x\n", + prStaRec->ucIndex, ucWTEntry, + prStaRec->fgIsInUse,prStaRec->ucStaState, + prBssInfo->ucPhyTypeSet, + prStaRec->ucDesiredPhyTypeSet)); + + DBGLOG(SW4, INFO,("Sta Operation 0x%x DesiredNontHtRateSet 0x%x Mcs 0x%x u2HtCapInfo 0x%x\n", + prStaRec->u2OperationalRateSet,prStaRec->u2DesiredNonHTRateSet,prStaRec->ucMcsSet, prStaRec->u2HtCapInfo)); + + + for(i = 0; iarTxQueue[i].u4NumElem)); + } + + DBGLOG(SW4, INFO, ("BmpDeliveryAC %x\n",prStaRec->ucBmpDeliveryAC)); + DBGLOG(SW4, INFO, ("BmpTriggerAC %x\n",prStaRec->ucBmpTriggerAC)); + DBGLOG(SW4, INFO, ("UapsdSpSupproted %u\n",prStaRec->fgIsUapsdSupported)); + DBGLOG(SW4, INFO, ("IsQoS %u\n",prStaRec->fgIsQoS)); + DBGLOG(SW4, INFO, ("AssocId %u\n",prStaRec->u2AssocId)); + + DBGLOG(SW4, INFO, ("fgIsInPS %u\n",prStaRec->fgIsInPS)); + DBGLOG(SW4, INFO, ("ucFreeQuota %u\n",prStaRec->ucFreeQuota)); + DBGLOG(SW4, INFO, ("ucFreeQuotaForDelivery %u\n",prStaRec->ucFreeQuotaForDelivery)); + DBGLOG(SW4, INFO, ("ucFreeQuotaForNonDelivery %u\n",prStaRec->ucFreeQuotaForNonDelivery)); + + +#if 0 + DBGLOG(SW4, INFO, ("IsQmmSup %u\n",prStaRec->fgIsWmmSupported)); + DBGLOG(SW4, INFO, ("IsUapsdSup %u\n",prStaRec->fgIsUapsdSupported)); + DBGLOG(SW4, INFO, ("AvailabaleDeliverPkts %u\n",prStaRec->ucAvailableDeliverPkts)); + DBGLOG(SW4, INFO, ("BmpDeliverPktsAC %u\n",prStaRec->u4BmpDeliverPktsAC)); + DBGLOG(SW4, INFO, ("BmpBufferAC %u\n",prStaRec->u4BmpBufferAC)); + DBGLOG(SW4, INFO, ("BmpNonDeliverPktsAC %u\n",prStaRec->u4BmpNonDeliverPktsAC)); +#endif + + for(i=0;iaprRxReorderParamRefTbl[i]){ + DBGLOG(SW4, INFO,("RxReorder fgIsValid: %u\n",prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid)); + DBGLOG(SW4, INFO,("RxReorder Tid: %u\n",prStaRec->aprRxReorderParamRefTbl[i]->ucTid)); + DBGLOG(SW4, INFO,("RxReorder rReOrderQue Len: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem)); + DBGLOG(SW4, INFO,("RxReorder WinStart: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart)); + DBGLOG(SW4, INFO,("RxReorder WinEnd: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd)); + DBGLOG(SW4, INFO,("RxReorder WinSize: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize)); + } + } + +} + + +VOID dumpBss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + + DBGLOG(SW4, INFO, ("SSID %s\n",prBssInfo->aucSSID)); + DBGLOG(SW4, INFO, ("OWN " MACSTR"\n",MAC2STR(prBssInfo->aucOwnMacAddr))); + DBGLOG(SW4, INFO, ("BSSID " MACSTR"\n",MAC2STR(prBssInfo->aucBSSID))); + DBGLOG(SW4, INFO, ("ucNetTypeIndex %u\n",prBssInfo->ucNetTypeIndex)); + DBGLOG(SW4, INFO, ("eConnectionState %u\n",prBssInfo->eConnectionState)); + DBGLOG(SW4, INFO, ("eCurrentOPMode %u\n",prBssInfo->eCurrentOPMode)); + DBGLOG(SW4, INFO, ("fgIsQBSS %u\n",prBssInfo->fgIsQBSS)); + DBGLOG(SW4, INFO, ("fgIsShortPreambleAllowed %u\n",prBssInfo->fgIsShortPreambleAllowed)); + DBGLOG(SW4, INFO, ("fgUseShortPreamble %u\n",prBssInfo->fgUseShortPreamble)); + DBGLOG(SW4, INFO, ("fgUseShortSlotTime %u\n",prBssInfo->fgUseShortSlotTime)); + DBGLOG(SW4, INFO, ("ucNonHTBasicPhyType %x\n",prBssInfo->ucNonHTBasicPhyType)); + DBGLOG(SW4, INFO, ("u2OperationalRateSet %x\n",prBssInfo->u2OperationalRateSet)); + DBGLOG(SW4, INFO, ("u2BSSBasicRateSet %x\n",prBssInfo->u2BSSBasicRateSet)); + DBGLOG(SW4, INFO, ("ucPhyTypeSet %x\n",prBssInfo->ucPhyTypeSet)); + DBGLOG(SW4, INFO, ("rStaRecOfClientList %d\n",prBssInfo->rStaRecOfClientList.u4NumElem)); + DBGLOG(SW4, INFO, ("u2CapInfo %x\n",prBssInfo->u2CapInfo)); + DBGLOG(SW4, INFO, ("u2ATIMWindow %x\n",prBssInfo->u2ATIMWindow)); + DBGLOG(SW4, INFO, ("u2AssocId %x\n",prBssInfo->u2AssocId)); + DBGLOG(SW4, INFO, ("ucDTIMPeriod %x\n",prBssInfo->ucDTIMPeriod)); + DBGLOG(SW4, INFO, ("ucDTIMCount %x\n",prBssInfo->ucDTIMCount)); + DBGLOG(SW4, INFO, ("fgIsNetAbsent %x\n", prBssInfo->fgIsNetAbsent)); + DBGLOG(SW4, INFO, ("eBand %d\n", prBssInfo->eBand)); + DBGLOG(SW4, INFO, ("ucPrimaryChannel %d\n", prBssInfo->ucPrimaryChannel)); + DBGLOG(SW4, INFO, ("ucHtOpInfo1 %d\n", prBssInfo->ucHtOpInfo1)); + DBGLOG(SW4, INFO, ("ucHtOpInfo2 %d\n", prBssInfo->u2HtOpInfo2)); + DBGLOG(SW4, INFO, ("ucHtOpInfo3 %d\n", prBssInfo->u2HtOpInfo3)); + DBGLOG(SW4, INFO, ("fgErpProtectMode %d\n", prBssInfo->fgErpProtectMode)); + DBGLOG(SW4, INFO, ("eHtProtectMode %d\n", prBssInfo->eHtProtectMode)); + DBGLOG(SW4, INFO, ("eGfOperationMode %d\n", prBssInfo->eGfOperationMode)); + DBGLOG(SW4, INFO, ("eRifsOperationMode %d\n", prBssInfo->eRifsOperationMode)); + DBGLOG(SW4, INFO, ("fgObssErpProtectMode %d\n", prBssInfo->fgObssErpProtectMode)); + DBGLOG(SW4, INFO, ("eObssHtProtectMode %d\n", prBssInfo->eObssHtProtectMode)); + DBGLOG(SW4, INFO, ("eObssGfProtectMode %d\n", prBssInfo->eObssGfOperationMode)); + DBGLOG(SW4, INFO, ("fgObssRifsOperationMode %d\n", prBssInfo->fgObssRifsOperationMode)); + DBGLOG(SW4, INFO, ("fgAssoc40mBwAllowed %d\n", prBssInfo->fgAssoc40mBwAllowed)); + DBGLOG(SW4, INFO, ("fg40mBwAllowed %d\n", prBssInfo->fg40mBwAllowed)); + DBGLOG(SW4, INFO, ("eBssSCO %d\n", prBssInfo->eBssSCO)); + + +} + + + +VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1) +{ + UINT_8 ucIndex,ucRead; + UINT_32 i; + + DEBUGFUNC("swCtrlCmdCategory0"); + + SWCR_GET_RW_INDEX(ucAction,ucRead,ucIndex); + + i=0; + + if(ucIndex>=SWCTRL_CATA0_INDEX_NUM) return; + + if(ucRead == SWCR_WRITE) { + switch(ucIndex) { + case SWCTRL_DEBUG: +#if DBG + aucDebugModule[ucOpt0] = (UINT_8)g_au4SwCr[1]; +#endif + break; + case SWCTRL_WIFI_VAR: + break; + +#if QM_DEBUG_COUNTER + case SWCTRL_DUMP_QM_DBG_CNT: + for(i=0;irQM.au4QmDebugCounters[i] = 0; + } + break; + case SWCTRL_QM_DBG_CNT: + prAdapter->rQM.au4QmDebugCounters[ucOpt0] = g_au4SwCr[1]; + + break; +#endif +#if CFG_RX_PKTS_DUMP + case SWCTRL_RX_PKTS_DUMP: + //DBGLOG(SW4, INFO,("SWCTRL_RX_PKTS_DUMP: mask %x\n", g_au4SwCr[1])); + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = g_au4SwCr[1]; + break; +#endif + case SWCTRL_RX_MDNS_FILTER: + { + UINT_32 u4rxfilter; + BOOLEAN fgUpdate = FALSE; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_STOP) { + g_u4mDNSRXFilter &= ~(RX_MDNS_FILTER_START); + + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } + else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_START) { + g_u4mDNSRXFilter |= (RX_MDNS_FILTER_START); + + u4rxfilter = prAdapter->u4OsPacketFilter; + if ((g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV4) && + (g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV6)) { + u4rxfilter &= ~(PARAM_PACKET_FILTER_ALL_MULTICAST| + PARAM_PACKET_FILTER_MULTICAST); + } + else { + u4rxfilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } + fgUpdate = TRUE; + } + else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_ADD) { + if (ucOpt1 < 31) { + g_u4mDNSRXFilter |= (1<rQM; + switch(ucOpt0) { + case 0: + g_au4SwCr[1] = (QM_GET_TX_QUEUE_LEN(prAdapter, ucOpt1)) ; + g_au4SwCr[2] = prQM->au4MinReservedTcResource[ucOpt1] ; + g_au4SwCr[3] = prQM->au4CurrentTcResource[ucOpt1]; + g_au4SwCr[4] = prQM->au4GuaranteedTcResource[ucOpt1]; + break; + + case 1: + g_au4SwCr[1] = prQM->au4ForwardCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; + break; + + case 2: + g_au4SwCr[1] = prQM->arTxQueue[ucOpt1].u4NumElem; /* only one */ + + + break; + } + + } + case SWCTRL_TX_CTRL_INFO: + { + P_TX_CTRL_T prTxCtrl; + prTxCtrl = &prAdapter->rTxCtrl; + switch(ucOpt0) { + case 0: + g_au4SwCr[1] = prAdapter->rTxCtrl.rTc.aucFreeBufferCount[ucOpt1]; + g_au4SwCr[2] = prAdapter->rTxCtrl.rTc.aucMaxNumOfBuffer[ucOpt1]; + break; + } + + } + break; + case SWCTRL_DUMP_QUEUE: + dumpQueue(prAdapter); + + break; +#if QM_DEBUG_COUNTER + case SWCTRL_DUMP_QM_DBG_CNT: + for(i=0;irQM.au4QmDebugCounters[i])); + } + break; + + case SWCTRL_QM_DBG_CNT: + g_au4SwCr[1] = prAdapter->rQM.au4QmDebugCounters[ucOpt0]; + break; +#endif + case SWCTRL_DUMP_BSS: + { + dumpBss(prAdapter, &(prAdapter->rWifiVar.arBssInfo[ucOpt0])) ; + } + break; + + default: + break; + } + + } +} + + +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1) +{ + UINT_8 ucIndex,ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("swCtrlCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction,ucRead,ucIndex); + + if(ucOpt0>=CFG_STA_REC_NUM) return; + + //prStaRec = cnmGetStaRecByIndex (prAdapter, ucOpt0); + prStaRec = &prAdapter->arStaRec[ucOpt0]; + ucWTEntry = prStaRec->ucWTEntry; + if(ucRead == SWCR_WRITE) { + } + else { + /* Read */ + switch(ucIndex) { + case SWCTRL_STA_QUE_INFO: + { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch(ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: + { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + + +} + +#if TEST_PS + +VOID +testPsSendQoSNullFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN UINT_8 ucNetTypeIndex, + IN BOOLEAN fgBMC, + IN BOOLEAN fgIsBurstEnd, + IN BOOLEAN ucPacketType, + IN BOOLEAN ucPsSessionID, + IN BOOLEAN fgSetEOSP + ) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, ("\n")); + + //4 <1> Allocate a PKT_INFO_T for Null Frame + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + \ + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == NULL) { + DBGLOG(SW4, WARN, ("No PKT_INFO_T for sending Null Frame.\n")); + return ; + } + + //4 <2> Compose Null frame in MSDU_INfO_T. + bssComposeQoSNullFrame(prAdapter, + (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, + ucUP, + fgSetEOSP); + + + prMsduInfo->eSrc = TX_PACKET_MGMT; + //prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; + prMsduInfo->ucPacketType = ucPacketType; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + prMsduInfo->fgIsBurstEnd = fgIsBurstEnd; + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPsSessionID = ucPsSessionID /* 0~7 Test 7 means NOACK*/; + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T)( (PUINT_8)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD) ); + + if(fgBMC) { + prQoSNullFrame->aucAddr1[0] = 0xfd; + } + else { + prQoSNullFrame->aucAddr1[5] = 0xdd; + } + + //4 <4> Inform TXM to send this Null frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + + + +VOID +testPsSetupBss( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucNetworkTypeIndex + ) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, ("index %d\n", ucNetworkTypeIndex)); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetworkTypeIndex]); + + //4 <1.2> Initiate PWR STATE + //SET_NET_PWR_STATE_IDLE(prAdapter, ucNetworkTypeIndex); + + + //4 <2> Initiate BSS_INFO_T - common part + BSS_INFO_INIT(prAdapter, ucNetworkTypeIndex); + + prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucNetTypeIndex = (ucNetworkTypeIndex); + prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->u2BSSBasicRateSet = RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->fgIsQBSS = TRUE; + + //4 <1.5> Setup MIB for current BSS + prBssInfo->u2BeaconInterval = 100; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + + prBssInfo->ucBeaconTimeoutCount = 0; + + + bssInitForAP (prAdapter,prBssInfo, TRUE); + + COPY_MAC_ADDR(prBssInfo->aucBSSID, _aucZeroMacAddr); + LINK_INITIALIZE(&prBssInfo->rStaRecOfClientList); + prBssInfo->fgIsBeaconActivated = TRUE; + prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; + + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + //4 <3> Initiate BSS_INFO_T - private part + /* TODO */ + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 1; + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T)NULL; + + + //prBssInfo->fgErpProtectMode = eErpProectMode; + //prBssInfo->eHtProtectMode = eHtProtectMode; + //prBssInfo->eGfOperationMode = eGfOperationMode; + + + //4 <4> Allocate MSDU_INFO_T for Beacon + prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prBssInfo->prBeacon) { + prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prBssInfo->prBeacon->ucNetworkType = ucNetworkTypeIndex; + } + else { + DBGLOG(SW4, INFO, ("prBeacon allocation fail\n")); + } + +#if 0 + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8)prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC =(UINT_8) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8)prAdapter->u4MaxSpLen; +#endif + +#if 0 + for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){ + + prBssInfo->arACQueParms[eAci].fgIsACMSet = FALSE; + prBssInfo->arACQueParms[eAci].u2Aifsn = (UINT_16) eAci; + prBssInfo->arACQueParms[eAci].u2CWmin = 7; + prBssInfo->arACQueParms[eAci].u2CWmax = 31; + prBssInfo->arACQueParms[eAci].u2TxopLimit = eAci+1; + DBGLOG(SW4, INFO, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci,prBssInfo->arACQueParms[eAci].fgIsACMSet , + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, + prBssInfo->arACQueParms[eAci].u2TxopLimit)); + + } +#endif + + + DBGLOG(SW4, INFO, ("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, + prBssInfo->rPmProfSetupInfo.ucUapsdSp)); + + return; +} + + + + +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1) +{ + UINT_8 ucIndex,ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction,ucRead,ucIndex); + + DBGLOG(SW4, LOUD, ("Read %u Index %u\n",ucRead,ucIndex)); + + prStaRec = cnmGetStaRecByIndex (prAdapter, 0); + + if(ucIndex>=TEST_PS_CATA0_INDEX_NUM) return; + + if(ucRead == SWCR_WRITE) { + switch(ucIndex) { + case TEST_PS_SETUP_BSS: + testPsSetupBss(prAdapter, ucOpt0) ; + break; + + case TEST_PS_ENABLE_BEACON: + break; + + case TEST_PS_TRIGGER_BMC: + //txmForwardQueuedBmcPkts (ucOpt0); + break; + case TEST_PS_SEND_NULL: + { + + testPsSendQoSNullFrame (prAdapter,prStaRec, + (UINT_8)(g_au4SwCr[1] & 0xFF), /* UP */ + ucOpt0, + (BOOLEAN)((g_au4SwCr[1] >>8)& 0xFF), /* BMC*/ + (BOOLEAN)((g_au4SwCr[1] >>16)& 0xFF), /* BurstEnd*/ + (BOOLEAN)((g_au4SwCr[1] >>24)& 0xFF), /* Packet type*/ + (UINT_8)((g_au4SwCr[2] )& 0xFF), /* PS sesson ID 7: NOACK */ + FALSE /* EOSP */ + ); + } + break; + case TEST_PS_BUFFER_BMC: + //g_aprBssInfo[ucOpt0]->fgApToBufferBMC = (g_au4SwCr[1] & 0xFF); + break; + case TEST_PS_UPDATE_BEACON: + bssUpdateBeaconContent(prAdapter, ucOpt0 /*networktype*/ ); + break; + + default: + break; + } + } + else { + switch(ucIndex) { + + case TEST_PS_MAGIC: + g_au4SwCr[1] = 0x88660011 ; + break; + + } + } +} + +#endif //TEST_PS + +#if TEST_PS + +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1) +{ + UINT_8 ucIndex,ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction,ucRead,ucIndex); + + if(ucOpt0>=CFG_STA_REC_NUM) return; + + prStaRec = cnmGetStaRecByIndex (prAdapter, ucOpt0); + ucWTEntry = prStaRec->ucWTEntry; + if(ucRead == SWCR_WRITE) { + + switch(ucIndex) { + case TEST_PS_STA_PS: + prStaRec->fgIsInPS = (BOOLEAN) (g_au4SwCr[1] & 0x1); + prStaRec->fgIsQoS = (BOOLEAN) (g_au4SwCr[1] >>8 & 0xFF); + prStaRec->fgIsUapsdSupported = (BOOLEAN) (g_au4SwCr[1] >>16 & 0xFF); + prStaRec->ucBmpDeliveryAC = (BOOLEAN) (g_au4SwCr[1] >>24 & 0xFF); + break; + + } + + } + else { + /* Read */ + switch(ucIndex) { + default: + break; + } + } + + +} + +#endif //TEST_PS + +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ==1) && (WNM_UNIT_TEST ==1) +VOID testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0,UINT_8 ucOpt1) +{ + UINT_8 ucIndex,ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testWNMCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction,ucRead,ucIndex); + + DBGLOG(SW4, INFO, ("Read %u Index %u\n",ucRead,ucIndex)); + + if(ucIndex>=TEST_WNM_CATA0_INDEX_NUM) return; + + if(ucRead == SWCR_WRITE) { + switch(ucIndex) { + case TEST_WNM_TIMING_MEAS: + wnmTimingMeasUnitTest1(prAdapter, ucOpt0) ; + break; + + default: + break; + } + } +} +#endif //TEST_WNM +#endif //CFG_SUPPORT_802_11V + +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + /* According other register STAIDX */ + UINT_8 ucOffset; + ucOffset = (u2Addr>>2) & 0x3F; + + if(ucOffset>= SWCR_CR_NUM) return; + + if(ucRead==SWCR_WRITE) { + g_au4SwCr[ucOffset] = *pu4Data; + if(ucOffset==0x0) { + /* Commmand [31:24]: Category */ + /* Commmand [23:23]: 1(W) 0(R) */ + /* Commmand [22:16]: Index */ + /* Commmand [15:08]: Option0 */ + /* Commmand [07:00]: Option1 */ + UINT_8 ucCate; + UINT_32 u4Cmd; + u4Cmd = g_au4SwCr[0]; + ucCate = (UINT_8)(u4Cmd >> 24) ; + if(ucCate < sizeof(g_arSwCtrlCmd)/sizeof(g_arSwCtrlCmd[0])) { + if(g_arSwCtrlCmd[ucCate]!=NULL) { + g_arSwCtrlCmd[ucCate](prAdapter, ucCate, (UINT_8)(u4Cmd>>16 & 0xFF),(UINT_8)((u4Cmd>>8) & 0xFF), (UINT_8)(u4Cmd&0xFF)); + } + } + } + } + else { + *pu4Data = g_au4SwCr[ucOffset]; + } +} + +VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + UINT_8 ucMod; + + ucMod = u2Addr >>8; + /* Address [15:8] MOD ID */ + /* Address [7:0] OFFSET */ + + DEBUGFUNC("swCrReadWriteCmd"); + DBGLOG(SW4, INFO, ("%u addr 0x%x data 0x%x\n",ucRead,u2Addr,*pu4Data)); + + if(ucMod < (sizeof(g_arSwCrModHandle)/sizeof(g_arSwCrModHandle[0])) ) { + + if(g_arSwCrModHandle[ucMod]!=NULL) { + g_arSwCrModHandle[ucMod](prAdapter, ucRead, u2Addr, pu4Data); + } + } /* ucMod */ +} + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType) +{ + g_u4SwcrDebugFrameDumpType = u4DumpType; + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +} + +VOID swCrDebugInit(P_ADAPTER_T prAdapter) +{ + // frame dump + if (g_u4SwcrDebugFrameDumpType) { + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + } + + // debug counter + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, + &g_rSwcrDebugTimer, + (PFN_MGMT_TIMEOUT_FUNC)swCrDebugCheckTimeout, + (UINT_32) NULL); + + if (g_u4SwcrDebugCheckTimeout) { + swCrDebugCheckEnable(prAdapter, TRUE, g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); + } +} + +VOID swCrDebugUninit(P_ADAPTER_T prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout) +{ + if (fgIsEnable) { + g_ucSwcrDebugCheckType = ucType; + g_u4SwcrDebugCheckTimeout = u4Timeout; + if (g_fgSwcrDebugTimer == FALSE) { + swCrDebugCheckTimeout(prAdapter, 0); + } + } + else { + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + g_u4SwcrDebugCheckTimeout = 0; + } + + g_fgSwcrDebugTimer = fgIsEnable; +} + +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + // dump counters + if (prCmdSwCtrl) { + if (prCmdSwCtrl->u4Data == SWCR_DBG_TYPE_ALL) { + + // TX Counter from fw + DBGLOG(SW4, INFO, ("TX0\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_BCN_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_FAILED_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_RETRY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_MGNT_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_ERROR_CNT])); +#if 1 + // TX Counter from drv + DBGLOG(SW4, INFO, ("TX1\n" \ + "%08x %08x %08x %08x\n", + (UINT_32)TX_GET_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP), + (UINT_32)TX_GET_CNT(prTxCtrl, TX_INACTIVE_STA_DROP), + (UINT_32)TX_GET_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP), + (UINT_32)TX_GET_CNT(prTxCtrl, TX_AP_BORADCAST_DROP))); +#endif + + // RX Counter + DBGLOG(SW4, INFO, ("RX0\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DUP_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FIFOFULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_PFDROP_CNT])); + + DBGLOG(SW4, INFO, ("RX1\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n", + (UINT_32)RX_GET_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT), + (UINT_32)RX_GET_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT))); + + DBGLOG(SW4, INFO, ("PWR\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PS_POLL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_IND_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE1], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF1])); + + DBGLOG(SW4, INFO, ("ARM\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RATE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_BWGI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ENABLE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ROAM_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_INT_CNT])); + + DBGLOG(SW4, INFO, ("BB\n" \ + "%08x %08x %08x %08x\n" \ + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_MDRDY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SFDERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SIGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT])); + + } + } + + // start the next check + if (g_u4SwcrDebugCheckTimeout) { + cnmTimerStartTimer(prAdapter, &g_rSwcrDebugTimer, g_u4SwcrDebugCheckTimeout * MSEC_PER_SEC); + } +} + +VOID swCrDebugCheckTimeout( + IN P_ADAPTER_T prAdapter, + UINT_32 u4Param) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rStatus; + + rCmdSwCtrl.u4Id = (0xb000<<16) + g_ucSwcrDebugCheckType; + rCmdSwCtrl.u4Data = 0; + rStatus = wlanSendSetQueryCmd ( + prAdapter, /* prAdapter */ + CMD_ID_SW_DBG_CTRL, /* ucCID */ + FALSE, /* fgSetQuery */ + TRUE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + swCrDebugQuery, /* pfCmdDoneHandler */ + swCrDebugQueryTimeout, /* pfCmdTimeoutHandler */ + sizeof(CMD_SW_DBG_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return; +} + +VOID swCrDebugQuery( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, (P_CMD_SW_DBG_CTRL_T)(pucEventBuf)); +} + +VOID swCrDebugQueryTimeout( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c new file mode 100755 index 000000000000..4d2337851489 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c @@ -0,0 +1,522 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/wapi.c#1 $ +*/ + +/*! \file "wapi.c" + \brief This file including the WAPI related function. + + This file provided the macros and functions library support the wapi ie parsing, + cipher and AKM check to help the AP seleced deciding. +*/ + + + +/* +** $Log: wapi.c $ +** +** 10 24 2012 wh.su +** [ALPS00376392] [klocwork 9.1] in wapi.c, line 344 +** Use MAX_NUM_SUPPORTED_WAPI_AKM_SUITESfor avoid Klocwork warning. +** +** 10 24 2012 wh.su +** [ALPS00376391] [klocwork 9.1] in wapi.c, line 311 +** Use the MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES for avoid Klccwork waring. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 20 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * fixed the network type + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 07 20 2010 wh.su + * + * . + * + * 04 06 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Microsoft os query + * fixed the firmware return the broadcast frame at wrong tc. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function to check and update the default wapi tx + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the generate wapi ie function, and replace the tabe by space + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" +#if CFG_SUPPORT_WAPI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID +wapiGenerateWAPIIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket + + (UINT_32)prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 68 :0x44 */ + if (/* prWlanInfo->fgWapiMode && */ prAdapter->prGlueInfo->u2WapiAssocInfoIESz) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWapiAssocInfoIEs, prAdapter->prGlueInfo->u2WapiAssocInfoIESz); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WapiAssocInfoIESz; + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse WAPI IE. +* +* \param[in] prInfoElem Pointer to the RSN IE +* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the +** WAPI information from the given WAPI IE +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wapiParseWapiIE ( + IN P_WAPI_INFO_ELEM_T prInfoElem, + OUT P_WAPI_INFO_T prWapiInfo + ) +{ + UINT_32 i; + INT_32 u4RemainWapiIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = WAPI_CIPHER_SUITE_WPI; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUCHAR pucPairSuite = NULL; + PUCHAR pucAuthSuite = NULL; + PUCHAR cp; + + DEBUGFUNC("wapiParseWapiIE"); + + ASSERT(prInfoElem); + ASSERT(prWapiInfo); + + /* Verify the length of the WAPI IE. */ + if (prInfoElem->ucLength < 6) { + DBGLOG(SEC, TRACE, ("WAPI IE length too short (length=%d)\n", prInfoElem->ucLength)); + return FALSE; + } + + /* Check WAPI version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(SEC, TRACE, ("Unsupported WAPI IE version: %d\n", u2Version)); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u2AuthKeyMgtSuiteCount; + u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainWapiIeLen == 0) { + break; + } + + /* + AuthCount : 2 + AuthSuite : 4 * authSuiteCount + PairwiseCount: 2 + PairwiseSuite: 4 * pairSuiteCount + GroupSuite : 4 + Cap : 2 */ + + /* Parse the Authentication and Key Management Cipher Suite Count + field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + if (u4RemainWapiIeLen == 0) { + break; + } + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWapiIeLen < 4) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWapiIeLen -= 4; + + /* Parse the WAPI u2Capabilities field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, ("Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n", + prInfoElem->ucLength)); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWapiIeLen -= 2; + + /* Todo:: BKID support */ + } while (FALSE); + + /* Save the WAPI information for the BSS. */ + + prWapiInfo->ucElemId = ELEM_ID_WAPI; + + prWapiInfo->u2Version = u2Version; + + prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(SEC, LOUD, ("WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF))); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES) { + u2PairSuiteCount = MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES; + } + + prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prWapiInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(SEC, LOUD,("WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for WAPI: WPI. */ + prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI; + + DBGLOG(SEC, LOUD, ("WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF))); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_WAPI_AKM_SUITES) { + u2AuthSuiteCount = MAX_NUM_SUPPORTED_WAPI_AKM_SUITES; + } + + prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, ("WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8)i, (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF))); + } + } + else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for WAPI. */ + prWapiInfo->u4AuthKeyMgtSuiteCount = 1; + prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X; + + DBGLOG(SEC, LOUD, ("WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF))); + } + + prWapiInfo->u2WapiCap = u2Cap; + DBGLOG(SEC, LOUD, ("WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap)); + + return TRUE; +} /* wapiParseWapiIE */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform WAPI policy selection for a given BSS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The WAPI policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The WAPI policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wapiPerformPolicySelection ( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss + ) +{ + UINT_32 i; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_WAPI_INFO_T prBssWapiInfo; + P_WLAN_INFO_T prWlanInfo; + + DEBUGFUNC("wapiPerformPolicySelection"); + + ASSERT(prBss); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */ + prWlanInfo = &prAdapter->rWlanInfo; + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } + else { + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE,("-- No Protected BSS\n")); + return TRUE; + } + else { + DBGLOG(SEC, TRACE, ("WAPI Information Element does not exist.\n")); + return FALSE; + } + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + BSS, do not check the supported AKM suites. */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, ("Failed to select pairwise/group cipher (0x%08lx/0x%08lx)\n", + u4PairwiseCipher, u4GroupCipher)); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + the given BSS, we fail to perform RSNA policy selection. */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { + u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(SEC, TRACE, ("Cannot support any AKM suites\n")); + return FALSE; + } + + DBGLOG(SEC, TRACE, ("Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF))); + + DBGLOG(SEC, TRACE, ("Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF))); + + return TRUE; +} /* wapiPerformPolicySelection */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 . +* +* \param[in] prStaRec Pointer to the Sta record +* \param[out] ucWlanIdx The Rx status->wlanidx field +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wapiUpdateTxKeyIdx ( + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucWlanIdx + ) +{ + UINT_8 ucKeyId; + + if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) { + + ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4); + + if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) { + DBGLOG(RSN, STATE, ("Change wapi key index from %d->%d\n", g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId)); + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId; + + prStaRec->ucWTEntry = + (ucKeyId == WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1; + } + } +} +#endif +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c new file mode 100755 index 000000000000..c6871df87ce7 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c @@ -0,0 +1,349 @@ +/* +** $Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/mgmt/wnm.c#1 $ +*/ + +/*! \file "wnm.c" + \brief This file includes the 802.11v default vale and functions. +*/ + + + +/* +** $Log: wnm.c $ + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_802_11V + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WNM_MAX_TOD_ERROR 0 +#define WNM_MAX_TOA_ERROR 0 +#define MICRO_TO_10NANO(x) ((x)*100) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT_8 ucTimingMeasToken = 0; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS +wnmRunEventTimgingMeasTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ); + +VOID +wnmComposeTimingMeasFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ); + +VOID +wnmTimingMeasRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v wnm category action frame. +* +* +* \note +* Called by: Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmWNMAction ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_ACTION_FRAME prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + if (prRxFrame->ucAction == ACTION_WNM_TIMING_MEASUREMENT_REQUEST) { + wnmTimingMeasRequest(prAdapter, prSwRfb); + return; + } +#endif + + DBGLOG(WNM, TRACE, ("Unsupport WNM action frame: %d\n", prRxFrame->ucAction)); +} + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to report timing measurement data. +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmReportTimingMeas ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIndex, + IN UINT_32 u4ToD, + IN UINT_32 u4ToA + ) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + return; + } + + DBGLOG(WNM, TRACE, ("wnmReportTimingMeas: u4ToD %x u4ToA %x", u4ToD, u4ToA)); + + if (!prStaRec->rWNMTimingMsmt.ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.u4ToD = MICRO_TO_10NANO(u4ToD); + prStaRec->rWNMTimingMsmt.u4ToA = MICRO_TO_10NANO(u4ToA); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(TimingMeasurement) Event. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Timing Measurement frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wnmRunEventTimgingMeasTxDone ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus + ) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(WNM, LOUD, ("EVENT-TX DONE: Current Time = %ld\n", kalGetTimeTick())); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + } + + DBGLOG(WNM, TRACE, ("wnmRunEventTimgingMeasTxDone: ucDialog %d ucFollowUp %d u4ToD %x u4ToA %x", + prStaRec->rWNMTimingMsmt.ucDialogToken, + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken, + prStaRec->rWNMTimingMsmt.u4ToD, + prStaRec->rWNMTimingMsmt.u4ToA)); + + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, NULL); + + return WLAN_STATUS_SUCCESS; + +} /* end of wnmRunEventTimgingMeasTxDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Timing Measurement frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmComposeTimingMeasFrame ( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler + ) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME) + ((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_UNPROTECTED_WNM_ACTION; + prTxFrame->ucAction = ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT; + + //3 Compose the frame body's frame. + prTxFrame->ucDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prTxFrame->ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken; + prTxFrame->u4ToD = prStaRec->rWNMTimingMsmt.u4ToD; + prTxFrame->u4ToA = prStaRec->rWNMTimingMsmt.u4ToA; + prTxFrame->ucMaxToDErr = WNM_MAX_TOD_ERROR; + prTxFrame->ucMaxToAErr = WNM_MAX_TOA_ERROR; + + u2PayloadLen = 2 + ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN; + + //4 Update information of MSDU_INFO_T + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + DBGLOG(WNM, TRACE, ("wnmComposeTimingMeasFrame: ucDialogToken %d ucFollowUpDialogToken %d u4ToD %x u4ToA %x\n", + prTxFrame->ucDialogToken, prTxFrame->ucFollowUpDialogToken, + prTxFrame->u4ToD, prTxFrame->u4ToA)); + + //4 Enqueue the frame to send this action frame. + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of wnmComposeTimingMeasFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v timing measurement request. +* +* +* \note +* Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmTimingMeasRequest ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_ACTION_WNM_TIMING_MEAS_REQ_FRAME prRxFrame = NULL; + P_STA_RECORD_T prStaRec; + + prRxFrame = (P_ACTION_WNM_TIMING_MEAS_REQ_FRAME)prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + return; + } + + DBGLOG(WNM, TRACE, ("IEEE 802.11: Received Timing Measuremen Request from " + MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + + // reset timing msmt + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = prRxFrame->ucTrigger; + if (!prRxFrame->ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + return; + } + + DBGLOG(WNM, INFO, ("IEEE 802.11v: Test Timing Measuremen Request from " + MACSTR"\n", MAC2STR(prStaRec->aucMacAddr))); + + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = 1; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} +#endif + +#endif /* CFG_SUPPORT_802_11V_TIMING_MEASUREMENT */ + +#endif /* CFG_SUPPORT_802_11V */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c new file mode 100755 index 000000000000..62653abf608a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c @@ -0,0 +1,218 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/cmd_buf.c#1 $ +*/ + +/*! \file "cmd_buf.c" + \brief This file contain the management function of internal Command Buffer + for CMD_INFO_T. + + We'll convert the OID into Command Packet and then send to FW. Thus we need + to copy the OID information to Command Buffer for following reasons. + 1. The data structure of OID information may not equal to the data structure of + Command, we cannot use the OID buffer directly. + 2. If the Command was not generated by driver we also need a place to store the + information. + 3. Because the CMD is NOT FIFO when doing memory allocation (CMD will be generated + from OID or interrupt handler), thus we'll use the Block style of Memory Allocation + here. +*/ + + + +/* +** $Log: cmd_buf.c $ + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. clear prPendingCmdInfo properly + * * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-13 21:59:08 GMT mtk01084 +** remove un-neceasary spaces +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-05-20 12:24:26 GMT mtk01461 +** Increase CMD Buffer - HIF_RX_HW_APPENDED_LEN when doing CMD_INFO_T allocation +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 09:41:08 GMT mtk01461 +** Add init of Driver Domain MCR flag and fix lint MTK WARN +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-17 19:51:45 GMT mtk01461 +** allocation function of CMD_INFO_T +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initial the MGMT memory pool for CMD Packet. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cmdBufInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_CMD_INFO_T prCmdInfo; + UINT_32 i; + + ASSERT(prAdapter); + + QUEUE_INITIALIZE(&prAdapter->rFreeCmdList); + + for (i = 0; i < CFG_TX_MAX_CMD_PKT_NUM; i++) { + prCmdInfo = &prAdapter->arHifCmdDesc[i]; + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + } + +} /* end of cmdBufInitialize() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] u4Length Length of the frame buffer to allocate. +* +* @retval NULL Pointer to the valid CMD Packet handler +* @retval !NULL Fail to allocat CMD Packet +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T +cmdBufAllocateCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Length + ) +{ + P_CMD_INFO_T prCmdInfo; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufAllocateCmdInfo"); + + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + /* Setup initial value in CMD_INFO_T */ + /* Start address of allocated memory */ + prCmdInfo->pucInfoBuffer = + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + + if (prCmdInfo->pucInfoBuffer == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + prCmdInfo = NULL; + } + else { + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + } + } + + return prCmdInfo; + +} /* end of cmdBufAllocateCmdInfo() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to free the CMD Packet to the MGMT memory pool. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo CMD Packet handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cmdBufFreeCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufFreeCmdInfo"); + + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo) { + if (prCmdInfo->pucInfoBuffer) { + cnmMemFree(prAdapter, prCmdInfo->pucInfoBuffer); + prCmdInfo->pucInfoBuffer = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + } + + return; + +} /* end of cmdBufFreeCmdPacket() */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c new file mode 100755 index 000000000000..ff64c681c619 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c @@ -0,0 +1,4425 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#2 $ +*/ + +/*! \file nic.c + \brief Functions that provide operation in NIC's (Network Interface Card) point of view. + + This file includes functions which unite multiple hal(Hardware) operations + and also take the responsibility of Software Resource Management in order + to keep the synchronization with Hardware Manipulation. +*/ + + + +/* +** $Log: nic.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 05 02 2012 terry.wu + * NULL + * Set the default value of AP StaRec index to "STA_REC_INDEX_NOT_FOUND" in update firmware bss command. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 11 22 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * keep debug counter setting after wake up. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 04 2011 cp.wu + * [WCXRP00001079] [MT5931][Driver] Release pending MMPDU only when BSS is being deactivated + * pre-check for NULL before calling MMPDU free function + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to the AP.. + * + * 10 11 2011 terry.wu + * NULL + * Rewrite Assert Dump Function for Portability. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * New CMD definition about RLM parameters + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * 1. correct logic + * 2. replace only BSS-DESC which doesn't have a valid SSID. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 05 12 2011 puff.wen + * NULL + * FW Assert information dump to driver + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 15 2011 cp.wu + * [WCXRP00000651] [MT6620 Wi-Fi][Driver] Refine RSSI buffering mechanism + * ROLLBACK due to the special design is to workaround incorrect initial RCPI value coming from firmware domain. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 14 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected + * 2. add dummy function for both Win32 and Linux part. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 12 2011 wh.su + * NULL + * enable the p2p check the cipher to set the bssInfo auth mode. + * + * 04 12 2011 wh.su + * NULL + * prepare the code for sync the auth mode and encryption status for P2P and BOW. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 04 10 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * Fix compiler issue. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 04 07 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside wlanAdapterStart + * . + * + * 04 07 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside wlanAdapterStart + * implementation of internal error handling of nicAllocateAdapterMemory. + * + * 03 31 2011 chinglan.wang + * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. + * . + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similiar APIs to hide the difference. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 08 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * Use kalPrint to print firmware assert info. + * + * 02 01 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * . + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 31 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * Print firmware ASSERT info at Android kernel log, driver side + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 19 2011 cp.wu + * [WCXRP00000372] [MT6620 Wi-Fi][Driver] Check bus access failure inside nicProcessIST() + * check bus error and/or card removal when retrieving interrupt status from HAL + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * 1) correct typo in scan.c + * 2) TX descriptors, RX descriptos and management buffer should use virtually continous buffer instead of physically contineous one + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 12 17 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 02 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Add more control value but dont use it now. + * + * 11 30 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Add auto rate check window in registry + * + * 11 10 2010 eddie.chen + * [WCXRP00000156] [MT6620][FW] Change Auto rate window to 64 and add throughput swcr + * Use autorate parameter 1 as phy rate mask. + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 10 18 2010 cp.wu + * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A + * reset ptrs when IEs are going to be dropped + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 26 2010 yuche.tsai + * NULL + * Fix someones coding error while enable WIFI_DIRECT. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 yuche.tsai + * NULL + * Add state change indication. + * + * 08 16 2010 yuche.tsai + * NULL + * Add support for P2P BSS update info. + * + * 08 12 2010 cp.wu + * NULL + * [removing debugging] not to dump beacon content. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 28 2010 cp.wu + * NULL + * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * FIX: structure of CMD_SET_BSS_INFO has been changed but no follow-ups are done. + * + * 07 22 2010 george.huang + * + * . + * + * 07 22 2010 george.huang + * + * Update fgIsQoS information in BSS INFO by CMD + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * update prStaRecOfAP with BSS-INFO. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occured + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill fgIsUapsdConnection when indicating BSS-CREATE with AIS-STA mode. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * correct nicProcessIST_impl() for interrupt status brought up by RX enhanced response + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always process TX interrupt first then RX interrupt. + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-16 18:03:43 GMT mtk02752 +** handling enhanced response which fields are fetched at different moments +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-15 17:00:29 GMT mtk02752 +** if RX enhanced response is used, D2H interrupt status should be coming from buffered result as well +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-15 12:01:55 GMT mtk02752 +** if TX_DONE bit is not set but WTSR0/WTSR1 is non-zero, then set TX_DONE bit due to time latency of interrupt status enhanced response +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:52:52 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-24 20:51:01 GMT mtk02752 +** integrate with SD1 by invoking qmHandleMailboxRxMessage() +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-16 17:32:33 GMT mtk02752 +** prepare code for invoking rxHandleMailboxRxMessage() +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:08 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-09 22:56:41 GMT mtk01084 +** modify HW access routines +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:20 GMT mtk01084 +** prevent warning +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:54:57 GMT mtk01084 +** init HIF +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:30 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:12 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-09-09 17:26:15 GMT mtk01084 +** modify for CFG_TEST_WITH_MT5921 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-19 10:55:22 GMT mtk01461 +** Unmask the unused HISR +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-18 15:59:13 GMT mtk01084 +** remove debug purpose code +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 14:05:02 GMT mtk01084 +** update for WIFI ownback part on initial +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-04 21:32:57 GMT mtk01084 +** add temporarily code to set driver own on adapter initialization +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:35:41 GMT mtk01461 +** Add init of TX aggregation and fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-24 21:12:10 GMT mtk01104 +** Add function nicRestoreSpiDefMode() +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:43:31 GMT mtk01461 +** Revise for MTK coding style - nicInitializeAdapter() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:52:47 GMT mtk01461 +** Update allocate Adapter Memory for MGMT Memory pool +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:57:08 GMT mtk01461 +** Refine the order of release memory from pucRxCoalescingBufCached +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-19 18:32:57 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:00:14 GMT mtk01426 +** Add CFG_SDIO_RX_ENHANCE support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:27 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:25:59 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const UINT_8 aucPhyCfg2PhyTypeSet[PHY_CONFIG_NUM] = +{ + PHY_TYPE_SET_802_11ABG, /* PHY_CONFIG_802_11ABG */ + PHY_TYPE_SET_802_11BG, /* PHY_CONFIG_802_11BG */ + PHY_TYPE_SET_802_11G, /* PHY_CONFIG_802_11G */ + PHY_TYPE_SET_802_11A, /* PHY_CONFIG_802_11A */ + PHY_TYPE_SET_802_11B, /* PHY_CONFIG_802_11B */ + PHY_TYPE_SET_802_11ABGN, /* PHY_CONFIG_802_11ABGN */ + PHY_TYPE_SET_802_11BGN, /* PHY_CONFIG_802_11BGN */ + PHY_TYPE_SET_802_11AN, /* PHY_CONFIG_802_11AN */ + PHY_TYPE_SET_802_11GN /* PHY_CONFIG_802_11GN */ +}; + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + #define REQ_GATING_ENABLE_H2D_INT BIT(31) + #define REQ_GATING_DISABLE_H2D_INT BIT(30) + #define ACK_GATING_ENABLE_D2H_INT BIT(31) + #define ACK_GATING_DISABLE_D2H_INT BIT(30) + + #define GATING_CONTROL_POLL_LIMIT 64 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static INT_EVENT_MAP_T arIntEventMapTable[] = { + {WHISR_ABNORMAL_INT, INT_EVENT_ABNORMAL}, + {WHISR_D2H_SW_INT, INT_EVENT_SW_INT}, + {WHISR_TX_DONE_INT, INT_EVENT_TX}, + {(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT), INT_EVENT_RX} +}; + +static const UINT_8 ucIntEventMapSize = (sizeof(arIntEventMapTable) / sizeof(INT_EVENT_MAP_T)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + nicProcessTxInterrupt, /*!< INT_EVENT_TX */ + nicProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*! This macro is used to reduce coding errors inside nicAllocateAdapterMemory() + * and also enhance the readability. + */ +#define LOCAL_NIC_ALLOCATE_MEMORY(pucMem, u4Size, eMemType, pucComment) \ + { \ + DBGLOG(INIT, INFO, ("Allocating %ld bytes for %s.\n", u4Size, pucComment)); \ + if ((pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType)) == (PUINT_8)NULL) { \ + DBGLOG(INIT, ERROR, ("Could not allocate %ld bytes for %s.\n", u4Size, pucComment)); \ + break; \ + } \ + ASSERT(((UINT_32)pucMem % 4) == 0); \ + DBGLOG(INIT, INFO, ("Virtual Address = %08lx for %s.\n", (UINT_32)pucMem, pucComment)); \ + } + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for the allocation of the data structures +* inside the Adapter structure, include: +* 1. SW_RFB_Ts +* 2. Common coalescing buffer for TX PATH. +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @retval WLAN_STATUS_SUCCESS - Has enough memory. +* @retval WLAN_STATUS_RESOURCES - Memory is not enough. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicAllocateAdapterMemory ( + IN P_ADAPTER_T prAdapter + ) +{ + WLAN_STATUS status = WLAN_STATUS_RESOURCES; + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + DEBUGFUNC("nicAllocateAdapterMemory"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + prTxCtrl = &prAdapter->rTxCtrl; + + do { + //4 <0> Reset all Memory Handler + #if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount = 0; + prAdapter->u4MemAllocDynamicCount = 0; + #endif + prAdapter->pucMgtBufCached = (PUINT_8)NULL; + prRxCtrl->pucRxCached = (PUINT_8)NULL; + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T)NULL; + + + //4 <1> Memory for Management Memory Pool and CMD_INFO_T + /* Allocate memory for the CMD_INFO_T and its MGMT memory pool. */ + prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; + + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, + VIR_MEM_TYPE, + "COMMON MGMT MEMORY POOL"); + + //4 <2> Memory for RX Descriptor + /* Initialize the number of rx buffers we will have in our queue. */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, and using + * this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * \ + ALIGN_4(sizeof(SW_RFB_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, + prRxCtrl->u4RxCachedSize, + VIR_MEM_TYPE, + "SW_RFB_T"); + + //4 <3> Memory for TX DEscriptor + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * \ + ALIGN_4(sizeof(MSDU_INFO_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, + prTxCtrl->u4TxCachedSize, + VIR_MEM_TYPE, + "MSDU_INFO_T"); + + //4 <4> Memory for Common Coalescing Buffer +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + prAdapter->pucCoalescingBufCached = (PUINT_8)NULL; + + /* Allocate memory for the common coalescing buffer. */ + prAdapter->u4CoalescingBufCachedSize = CFG_COALESCING_BUFFER_SIZE > CFG_RX_COALESCING_BUFFER_SIZE ? + CFG_COALESCING_BUFFER_SIZE : CFG_RX_COALESCING_BUFFER_SIZE; + + prAdapter->pucCoalescingBufCached = + kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); + + if(prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(INIT, ERROR, ("Could not allocate %ld bytes for coalescing buffer.\n", prAdapter->u4CoalescingBufCachedSize)); + break; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + //4 <5> Memory for enhanced interrupt response + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if(prAdapter->prSDIOCtrl == NULL) { + DBGLOG(INIT, ERROR, ("Could not allocate %ld bytes for interrupt response.\n", sizeof(ENHANCE_MODE_DATA_STRUCT_T))); + break; + } + + status = WLAN_STATUS_SUCCESS; + + } + while(FALSE); + + if(status != WLAN_STATUS_SUCCESS) { + nicReleaseAdapterMemory(prAdapter); + } + + return status; + +} /* end of nicAllocateAdapterMemory() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for releasing the allocated memory by +* nicAllocatedAdapterMemory(). +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicReleaseAdapterMemory ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + //4 <5> Memory for enhanced interrupt response + if (prAdapter->prSDIOCtrl) { + kalReleaseIOBuffer((PVOID)prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T)NULL; + } + + //4 <4> Memory for Common Coalescing Buffer +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + if (prAdapter->pucCoalescingBufCached) { + kalReleaseIOBuffer((PVOID)prAdapter->pucCoalescingBufCached, prAdapter->u4CoalescingBufCachedSize); + prAdapter->pucCoalescingBufCached = (PUINT_8)NULL; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + //4 <3> Memory for TX Descriptor + if (prTxCtrl->pucTxCached) { + kalMemFree((PVOID)prTxCtrl->pucTxCached, + VIR_MEM_TYPE, + prTxCtrl->u4TxCachedSize); + prTxCtrl->pucTxCached = (PUINT_8)NULL; + } + + //4 <2> Memory for RX Descriptor + if (prRxCtrl->pucRxCached) { + kalMemFree((PVOID)prRxCtrl->pucRxCached, + VIR_MEM_TYPE, + prRxCtrl->u4RxCachedSize); + prRxCtrl->pucRxCached = (PUINT_8)NULL; + } + + //4 <1> Memory for Management Memory Pool + if (prAdapter->pucMgtBufCached) { + kalMemFree((PVOID)prAdapter->pucMgtBufCached, + VIR_MEM_TYPE, + prAdapter->u4MgtBufCachedSize); + prAdapter->pucMgtBufCached = (PUINT_8)NULL; + } + +#if CFG_DBG_MGT_BUF + /* Check if all allocated memories are free */ + ASSERT(prAdapter->u4MemFreeDynamicCount == + prAdapter->u4MemAllocDynamicCount); +#endif + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicDisableInterrupt ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicEnableInterrupt ( + IN P_ADAPTER_T prAdapter + ) +{ + BOOLEAN fgIsIntEnableCache; + + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + + prAdapter->fgIsIntEnable = TRUE; // NOTE(Kevin): It must be placed before MCR GINT write. + + /* If need enable INT and also set LPOwn at the same time. */ + if (prAdapter->fgIsIntEnableWithLPOwnSet) { + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; /* NOTE(Kevin): It's better to place it + * before MCR GINT write. + */ + /* If INT was enabled, only set LPOwn */ + if (fgIsIntEnableCache) { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + prAdapter->fgIsFwOwn = TRUE; + } + /* If INT was not enabled, enable it and also set LPOwn now */ + else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET | + WHLPCR_INT_EN_SET); + prAdapter->fgIsFwOwn = TRUE; + } + } + /* If INT was not enabled, enable it now */ + else if (!fgIsIntEnableCache) { + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + } + + return; +} /* end of nicEnableInterrupt() */ + + +#if CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief For SDIO enhance mode, set the max rx len and tx status +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicSDIOInit ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + + //4 <1> Check STATUS Buffer is DW alignment. + ASSERT( IS_ALIGN_4( (UINT_32)&prAdapter->prSDIOCtrl->u4WHISR ) ); + + //4 <2> Setup STATUS count. + { + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value); + + //4 <2.1> Setup the number of maximum RX length to be report + u4Value &= ~(WHCR_MAX_HIF_RX_LEN_NUM); + u4Value |= ((SDIO_MAXIMUM_RX_LEN_NUM << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM)); + + //4 <2.2> Setup RX enhancement mode +#if CFG_SDIO_RX_ENHANCE + u4Value |= WHCR_RX_ENHANCE_MODE_EN; +#else + u4Value &= ~WHCR_RX_ENHANCE_MODE_EN; +#endif /* CFG_SDIO_RX_AGG */ + + HAL_MCR_WR(prAdapter, MCR_WHCR, u4Value); + } + + return; + +} /* end of nicSDIOInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicSDIOReadIntStatus ( + IN P_ADAPTER_T prAdapter, + OUT PUINT_32 pu4IntStatus + ) +{ + P_SDIO_CTRL_T prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(ENHANCE_MODE_DATA_STRUCT_T), + (PUINT_8)prSDIOCtrl, + sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + /* workaround */ + if((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + + return; +} /* end of nicSDIOReadIntStatus() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to read interrupt status and then invoking +* dispatching procedure for the appropriate functions +* corresponding to specific interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicProcessIST ( + IN P_ADAPTER_T prAdapter + ) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4IntStatus = 0; + UINT_32 i; + + DEBUGFUNC("nicProcessIST"); + //DBGLOG(INIT, LOUD, ("\n")); + + ASSERT(prAdapter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, ("Fail in set nicProcessIST! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff)); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == TRUE) { + nicDisableClockGating(prAdapter); + } +#endif + + for (i = 0; i < CFG_IST_LOOP_COUNT; i++) { + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOReadIntStatus(prAdapter, &u4IntStatus); +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + //DBGLOG(INIT, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); + + if (u4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, ("Un-handled HISR %#x, HISR = %#x (HIER:0x%x)\n", + (u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, WHIER_DEFAULT)); + u4IntStatus &= WHIER_DEFAULT; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + if(u4IntStatus == 0) { + if(i == 0) { + u4Status = WLAN_STATUS_NOT_INDICATING; + } + break; + } + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if(prAdapter->fgIsClockGatingEnabled == FALSE) { + nicEnableClockGating(prAdapter); + } +#endif + + return u4Status; +} /* end of nicProcessIST() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to dispatch the appropriate functions for specific +* interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* u4IntStatus interrupt status bits +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicProcessIST_impl ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4IntStatus + ) +{ + UINT_32 u4IntCount = 0; + P_INT_EVENT_MAP_T prIntEventMap = NULL; + + ASSERT(prAdapter); + + prAdapter->u4IntStatus = u4IntStatus; + + /* Process each of the interrupt status consequently */ + prIntEventMap = &arIntEventMapTable[0]; + for (u4IntCount = 0; u4IntCount < ucIntEventMapSize; prIntEventMap++, u4IntCount++) { + if (prIntEventMap->u4Int & prAdapter->u4IntStatus) { + if(prIntEventMap->u4Event == INT_EVENT_RX && + prAdapter->fgIsEnterD3ReqIssued == TRUE) { + // ignore + } + else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { + apfnEventFuncTable[prIntEventMap->u4Event](prAdapter); + } + else { + DBGLOG(INTR , WARN, + ("Empty INTR handler! ISAR bit#: %ld, event:%d, func: 0x%x\n", + prIntEventMap->u4Int, prIntEventMap->u4Event, apfnEventFuncTable[prIntEventMap->u4Event])); + + ASSERT(0); // to trap any NULL interrupt handler + } + prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicProcessIST_impl() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Verify the CHIP ID +* +* @param prAdapter a pointer to adapter private data structure. +* +* +* @retval TRUE CHIP ID is the same as the setting compiled +* @retval FALSE CHIP ID is different from the setting compiled +*/ +/*----------------------------------------------------------------------------*/ +BOOL +nicVerifyChipID ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4CIR = 0; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR ); + + DBGLOG(INIT, TRACE,("Chip ID: 0x%x\n", u4CIR & WCIR_CHIP_ID)); + DBGLOG(INIT, TRACE,("Revision ID: 0x%x\n", ((u4CIR & WCIR_REVISION_ID) >> 16))); + + if ((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV) { + return FALSE; + } + + prAdapter->ucRevID = (UINT_8)(((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF) ; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the MCR to the appropriate init value, and verify the init +* value +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicMCRInit ( + IN P_ADAPTER_T prAdapter + ) +{ + + ASSERT(prAdapter); + + //4 <0> Initial value +} + +VOID +nicHifInit ( + IN P_ADAPTER_T prAdapter + ) +{ + + ASSERT(prAdapter); +#if 0 + /* reset event */ + nicPutMailbox(prAdapter, 0, 0x52455345); // RESE + nicPutMailbox(prAdapter, 1, 0x545F5746); // T_WF + nicSetSwIntr(prAdapter, BIT(16)); +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the Adapter soft variable +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicInitializeAdapter ( + IN P_ADAPTER_T prAdapter + ) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + + //4 <1> MCR init + nicMCRInit(prAdapter); + + #if CFG_SDIO_INTR_ENHANCE + nicSDIOInit(prAdapter); + #endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + + //4 <2> init FW HIF + nicHifInit(prAdapter); + } + while (FALSE); + + + return u4Status; +} + + +#if defined(_HIF_SPI) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Restore the SPI Mode Select to default mode, +* this is important while driver is unload, and this must be last mcr +* since the operation will let the hif use 8bit mode access +* +* \param[in] prAdapter a pointer to adapter private data structure. +* \param[in] eGPIO2_Mode GPIO2 operation mode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void +nicRestoreSpiDefMode ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicProcessAbnormalInterrupt ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4Value; + + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + DBGLOG(REQ, WARN, ("MCR_WASR: 0x%x \n", u4Value)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicProcessFwOwnBackInterrupt( + IN P_ADAPTER_T prAdapter + ) +{ + + return; +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicProcessSoftwareInterrupt( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4IntrBits; + + ASSERT(prAdapter); + + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + if((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + nicPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + ASSERT((u4IntrBits & (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)) + != (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)); + + if(u4IntrBits & ACK_GATING_ENABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = TRUE; + } + + if(u4IntrBits & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + + // Indicate Service Thread for TX + if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 + || wlanGetTxPendingFrameCount(prAdapter) > 0) { + kalSetEvent(prAdapter->prGlueInfo); + } + } +#endif + + DBGLOG(REQ, WARN, ("u4IntrBits: 0x%x \n", u4IntrBits)); + + return; +} /* end of nicProcessSoftwareInterrupt() */ + +VOID +nicPutMailbox ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4MailboxNum, + IN UINT_32 u4Data + ) +{ + if (u4MailboxNum == 0) { + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + } else if (u4MailboxNum == 1) { + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + } else { + ASSERT(0); + } +} + +VOID +nicGetMailbox ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4MailboxNum, + OUT PUINT_32 pu4Data + ) +{ + if (u4MailboxNum == 0) { + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + } else if (u4MailboxNum == 1) { + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + } else { + ASSERT(0); + } +} + +VOID +nicSetSwIntr ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4SwIntrBitmap + ) +{ + /* NOTE: + * SW interrup in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); +// DBGLOG(INIT, TRACE, ("u4SwIntrBitmap: 0x%08x\n", u4SwIntrBitmap)); + + HAL_MCR_WR(prAdapter, MCR_WSICR, u4SwIntrBitmap); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rPendingCmdQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_CMD_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T +nicGetPendingCmdInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if(prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + prCmdInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + return prCmdInfo; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rTxCtrl.rTxMgmtTxingQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_MSDU_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +nicGetPendingTxMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum + ) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T)prQueueEntry; + + if(prMsduInfo->ucTxSeqNum == ucSeqNum) + break; + else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfo; +} + +P_MSDU_INFO_T +nicGetPendingStaMMPDU ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx + ) +{ + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T)NULL; + P_QUE_T prTxingQue = (P_QUE_T)NULL; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + do { + if (prAdapter == NULL) { + + ASSERT(FALSE); + break; + } + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T)prQueueEntry; + + if ((prMsduInfo->ucStaRecIndex == ucStaRecIdx) && (prMsduInfo->pfTxDoneHandler != NULL)) { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfo, + prMsduInfoListHead); + prMsduInfoListHead = prMsduInfo; + } + else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + + return prMsduInfoListHead; +} /* nicGetPendingStaMMPDU */ + + +VOID +nicFreePendingTxMsduInfoByNetwork ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T)NULL; + P_MSDU_INFO_T prMsduInfoListTail = (P_MSDU_INFO_T)NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T)prQueueEntry; + + if((ENUM_NETWORK_TYPE_INDEX_T)(prMsduInfo->ucNetworkType) == eNetworkType) { + if(prMsduInfoListHead == NULL) { + prMsduInfoListHead = prMsduInfoListTail = prMsduInfo; + } + else { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, prMsduInfo); + prMsduInfoListTail = prMsduInfo; + } + } + else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* free */ + if(prMsduInfoListHead) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + } + + return; + +} /* end of nicFreePendingTxMsduInfoByNetwork() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a CMD sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +nicIncreaseCmdSeqNum ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + prAdapter->ucCmdSeqNum++; + ucRetval = prAdapter->ucCmdSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + return ucRetval; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a TX sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +nicIncreaseTxSeqNum ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + prAdapter->ucTxSeqNum++; + ucRetval = prAdapter->ucTxSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + return ucRetval; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to handle +* media state change event +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicMediaStateChange ( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN P_EVENT_CONNECTION_STATUS prConnectionStatus + ) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch(eNetworkType) { + case NETWORK_TYPE_AIS_INDEX: + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { // disconnected + if(kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + + /* reset buffered link quality information */ + prAdapter->fgIsLinkQualityValid = FALSE; + prAdapter->fgIsLinkRateValid = FALSE; + } + else if(prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { // connected + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + // fill information for association result + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen + = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, + prConnectionStatus->ucSsidLen); + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, + MAC_ADDR_LEN); + prAdapter->rWlanInfo.rCurrBssId.u4Privacy + = prConnectionStatus->ucEncryptStatus; // @FIXME + prAdapter->rWlanInfo.rCurrBssId.rRssi + = 0; //@FIXME + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse + = PARAM_NETWORK_TYPE_AUTOMODE; //@FIXME + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType + = prConnectionStatus->ucNetworkType; + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = (ENUM_PARAM_OP_MODE_T) prConnectionStatus->ucInfraMode; + + // always indicate to OS according to MSDN (re-association/roaming) + if(kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, + NULL, + 0); + } + else { + /* connected -> connected : roaming ? */ + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_ROAM_OUT_FIND_BEST, + NULL, + 0); + } + } + break; + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW_INDEX: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P_INDEX: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to convert between +* frequency and channel number +* +* @param u4ChannelNum +* +* @retval - Frequency in unit of KHz, 0 for invalid channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicChannelNum2Freq ( + UINT_32 u4ChannelNum + ) +{ + UINT_32 u4ChannelInMHz; + + if(u4ChannelNum >= 1 && u4ChannelNum <= 13) { + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + } + else if(u4ChannelNum == 14) { + u4ChannelInMHz = 2484; + } + else if(u4ChannelNum == 133) { + u4ChannelInMHz = 3665; // 802.11y + } + else if(u4ChannelNum == 137) { + u4ChannelInMHz = 3685; // 802.11y + } + else if(u4ChannelNum >= 34 && u4ChannelNum <= 165) { + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + } + else if(u4ChannelNum >= 183 && u4ChannelNum <= 196) { + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + } + else { + u4ChannelInMHz = 0; + } + + return 1000 * u4ChannelInMHz; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to convert between +* frequency and channel number +* +* @param u4FreqInKHz +* +* @retval - Frequency Number, 0 for invalid freqency +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicFreq2ChannelNum ( + UINT_32 u4FreqInKHz + ) +{ + switch(u4FreqInKHz) { + case 2412000: + return 1; + case 2417000: + return 2; + case 2422000: + return 3; + case 2427000: + return 4; + case 2432000: + return 5; + case 2437000: + return 6; + case 2442000: + return 7; + case 2447000: + return 8; + case 2452000: + return 9; + case 2457000: + return 10; + case 2462000: + return 11; + case 2467000: + return 12; + case 2472000: + return 13; + case 2484000: + return 14; + case 3665000: + return 133; // 802.11y + case 3685000: + return 137; // 802.11y + case 4915000: + return 183; + case 4920000: + return 184; + case 4925000: + return 185; + case 4930000: + return 186; + case 4935000: + return 187; + case 4940000: + return 188; + case 4945000: + return 189; + case 4960000: + return 192; + case 4980000: + return 196; + case 5170000: + return 34; + case 5180000: + return 36; + case 5190000: + return 38; + case 5200000: + return 40; + case 5210000: + return 42; + case 5220000: + return 44; + case 5230000: + return 46; + case 5240000: + return 48; + case 5250000: + return 50; + case 5260000: + return 52; + case 5270000: + return 54; + case 5280000: + return 56; + case 5290000: + return 58; + case 5300000: + return 60; + case 5320000: + return 64; + case 5500000: + return 100; + case 5520000: + return 104; + case 5540000: + return 108; + case 5560000: + return 112; + case 5580000: + return 116; + case 5600000: + return 120; + case 5620000: + return 124; + case 5640000: + return 128; + case 5660000: + return 132; + case 5680000: + return 136; + case 5700000: + return 140; + case 5745000: + return 149; + case 5765000: + return 153; + case 5785000: + return 157; + case 5805000: + return 161; + case 5825000: + return 165; + default: + return 0; + } +} + + +/* firmware command wrapper */ +/* NETWORK (WIFISYS) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to activate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicActivateNetwork( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 1; + + if (((UINT_8) eNetworkTypeIdx) < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]; + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_BSS_ACTIVATE_CTRL), + (PUINT_8)&rCmdActivateCtrl, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to deactivate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicDeactivateNetwork( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + WLAN_STATUS u4Status; + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 0; + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_BSS_ACTIVATE_CTRL), + (PUINT_8)&rCmdActivateCtrl, + NULL, + 0); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + nicFreePendingTxMsduInfoByNetwork(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); + + return u4Status; +} + + +/* BSS-INFO */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to sync bss info with firmware +* when a new BSS has been connected or disconnected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateBss( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + WLAN_STATUS u4Status; + P_BSS_INFO_T prBssInfo; + CMD_SET_BSS_INFO rCmdSetBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + rCmdSetBssInfo.ucConnectionState = (UINT_8)prBssInfo->eConnectionState; + rCmdSetBssInfo.ucCurrentOPMode = (UINT_8)prBssInfo->eCurrentOPMode; + rCmdSetBssInfo.ucSSIDLen = (UINT_8)prBssInfo->ucSSIDLen; + kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); + rCmdSetBssInfo.ucIsQBSS = (UINT_8)prBssInfo->fgIsQBSS; + rCmdSetBssInfo.ucNonHTBasicPhyType = prBssInfo->ucNonHTBasicPhyType; + rCmdSetBssInfo.u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + rCmdSetBssInfo.u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + COPY_MAC_ADDR(rCmdSetBssInfo.aucOwnMac, prBssInfo->aucOwnMacAddr); + } +#endif + + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, prBssInfo); + + rCmdSetBssInfo.fgWapiMode = (UINT_8)FALSE; + + if(rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + rCmdSetBssInfo.ucAuthMode = (UINT_8)prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (UINT_8)prConnSettings->eEncStatus; + rCmdSetBssInfo.fgWapiMode = (UINT_8)prConnSettings->fgWapiMode; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if(rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + //P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + rCmdSetBssInfo.ucAuthMode = (UINT_8)AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8)ENUM_ENCRYPTION3_KEY_ABSENT; + } +#endif + else { +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8)AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8)ENUM_ENCRYPTION3_KEY_ABSENT; + } + else { + rCmdSetBssInfo.ucAuthMode = (UINT_8)AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = (UINT_8)ENUM_ENCRYPTION_DISABLED; + } + /* Need the probe response to detect the PBC overlap */ + rCmdSetBssInfo.fgIsApMode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); + } +#else + rCmdSetBssInfo.ucAuthMode = (UINT_8)AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8)ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + + if(eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + + cnmAisInfraConnectNotify(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + else if (eNetworkTypeIdx == NETWORK_TYPE_BOW_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_BOW && + prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else { + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + } + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BSS_INFO, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_BSS_INFO), + (PUINT_8)&rCmdSetBssInfo, + NULL, + 0); + + /* if BSS-INFO is going to be disconnected state, free all correlated station records */ + if(prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + /* clear client list */ + bssClearClientList(prAdapter, prBssInfo); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); + } + + return u4Status; +} + + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been created. (for AdHoc / P2P-GO) +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicPmIndicateBssCreated( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssCreated.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + rCmdIndicatePmBssCreated.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssCreated.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssCreated.u2AtimWindow = prBssInfo->u2ATIMWindow; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_CREATED, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_CREATED), + (PUINT_8)&rCmdIndicatePmBssCreated, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been connected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicPmIndicateBssConnected( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssConnected.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + rCmdIndicatePmBssConnected.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssConnected.u2AssocId = prBssInfo->u2AssocId; + rCmdIndicatePmBssConnected.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssConnected.u2AtimWindow = prBssInfo->u2ATIMWindow; + + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC; + + //DBGPRINTF("nicPmIndicateBssConnected: ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x", + //rCmdIndicatePmBssConnected.ucBmpDeliveryAC, + //rCmdIndicatePmBssConnected.ucBmpTriggerAC); + + if ((eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX) +#if CFG_ENABLE_WIFI_DIRECT + || ((eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if(prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = (UINT_8)prBssInfo->prStaRecOfAP->fgIsUapsdSupported; + } + else { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; //@FIXME + } + } + else { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_CONNECTED, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_CONNECTED), + (PUINT_8)&rCmdIndicatePmBssConnected, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been disconnected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicPmIndicateBssAbort( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdIndicatePmBssAbort.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_ABORT), + (PUINT_8)&rCmdIndicatePmBssAbort, + NULL, + 0); +} + +WLAN_STATUS +nicConfigPowerSaveProfile ( + IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + PARAM_POWER_MODE ePwrMode, + BOOLEAN fgEnCmdEvent + ) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(INIT, TRACE, ("eNetTypeIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", + eNetTypeIndex, ePwrMode, fgEnCmdEvent)); + + ASSERT(prAdapter); + + if (eNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } + +// prAdapter->rWlanInfo.ePowerSaveMode.ucNetTypeIndex = eNetTypeIndex; +// prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile = (UINT_8)ePwrMode; + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucNetTypeIndex = eNetTypeIndex; + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucPsProfile = (UINT_8)ePwrMode; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + TRUE, + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&(prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex]), + NULL, + sizeof(PARAM_POWER_MODE) + ); + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate firmware domain +* for beacon generation parameters +* +* @param prAdapter Pointer of ADAPTER_T +* eIeUpdMethod, Update Method +* eNetTypeIndex Index of Network +* u2Capability Capability +* aucIe Pointer to buffer of IEs +* u2IELen Length of IEs +* +* @retval - WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* WLAN_STATUS_PENDING +* WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateBeaconIETemplate ( + IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, + IN PUINT_8 aucIe, + IN UINT_16 u2IELen + ) +{ + P_CMD_BEACON_TEMPLATE_UPDATE prCmdBcnUpdate; + UINT_16 u2CmdBufLen = 0; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanUpdateBeaconIETemplate"); + DBGLOG(INIT, LOUD, ("\n")); + + printk("nicUpdateBeaconIETemplate\n"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + if (u2IELen > MAX_IE_LENGTH) { + return WLAN_STATUS_INVALID_DATA; + } + + if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_RANDOM + || eIeUpdMethod == IE_UPD_METHOD_UPDATE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; + } + else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, u2IELen); + } + else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + // prepare command info + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u2CmdBufLen)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n")); + printk("Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + // increase command sequence number + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, ("ucCmdSeqNum =%d\n", ucCmdSeqNum)); + + // Setup common CMD Info Packet + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = eNetTypeIndex; + prCmdInfo->u2InfoBufLen = (UINT_16)(CMD_HDR_SIZE + u2CmdBufLen); + prCmdInfo->pfCmdDoneHandler = NULL; //@FIXME + prCmdInfo->pfCmdTimeoutHandler = NULL; //@FIXME + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_UPDATE_BEACON_CONTENT; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u2CmdBufLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + // Setup WIFI_CMD_T (no payload) + prWifiCmd = (P_WIFI_CMD_T)(prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdBcnUpdate = (P_CMD_BEACON_TEMPLATE_UPDATE)(prWifiCmd->aucBuffer); + + // fill beacon updating command + prCmdBcnUpdate->ucUpdateMethod = (UINT_8) eIeUpdMethod; + prCmdBcnUpdate->ucNetTypeIndex = (UINT_8) eNetTypeIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if(u2IELen > 0 ) { + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + } + + // insert into prCmdQueue + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + + // wakeup txServiceThread later + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to initialization PHY related +* varaibles +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicSetAvailablePhyTypeSet ( + IN P_ADAPTER_T prAdapter + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = + aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) { + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; + } + /* NOTE(Kevin): Because we don't have N only mode, TBD */ + else /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ { + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicQmUpdateWmmParms( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + P_BSS_INFO_T prBssInfo; + CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + DBGLOG(QM, EVENT, ("sizeof(AC_QUE_PARMS_T): %d \n", sizeof(AC_QUE_PARMS_T))); + DBGLOG(QM, EVENT, ("sizeof(CMD_UPDATE_WMM_PARMS): %d \n", sizeof(CMD_UPDATE_WMM_PARMS_T))); + DBGLOG(QM, EVENT, ("sizeof(WIFI_CMD_T): %d \n", sizeof(WIFI_CMD_T))); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + rCmdUpdateWmmParms.ucNetTypeIndex = (UINT_8)eNetworkTypeIdx; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], &prBssInfo->arACQueParms[0], + (sizeof(AC_QUE_PARMS_T)*AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_WMM_PARMS, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_UPDATE_WMM_PARMS_T), + (PUINT_8)&rCmdUpdateWmmParms, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power gain corresponding to +* each band/modulation combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateTxPower( + IN P_ADAPTER_T prAdapter, + IN P_CMD_TX_PWR_T prTxPwrParam + ) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_TX_PWR_T), + (PUINT_8)prTxPwrParam, + NULL, + 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to set auto tx power parameter +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of Auto TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicSetAutoTxPower( + IN P_ADAPTER_T prAdapter, + IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam + ) +{ + DEBUGFUNC("nicSetAutoTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_AUTOPWR_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_AUTO_POWER_PARAM_T), + (PUINT_8)prAutoPwrParam, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power gain corresponding to +* each band/modulation combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicSetAutoTxPowerControl( + IN P_ADAPTER_T prAdapter, + IN P_CMD_TX_PWR_T prTxPwrParam + ) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_TX_PWR_T), + (PUINT_8)prTxPwrParam, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update power offset around 5GHz band +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of 5GHz power offset parameter +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdate5GOffset( + IN P_ADAPTER_T prAdapter, + IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset + ) +{ + DEBUGFUNC("nicUpdate5GOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_PWR_OFFSET, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_5G_PWR_OFFSET_T), + (PUINT_8)pr5GPwrOffset, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update DPD calibration result +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of parameter for DPD calibration result +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateDPD( + IN P_ADAPTER_T prAdapter, + IN P_CMD_PWR_PARAM_T prDpdCalResult + ) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_PWR_PARAM_T), + (PUINT_8)prDpdCalResult, + NULL, + 0); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function starts system service such as timer and +* memory pools +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicInitSystemService ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + // <1> Initialize MGMT Memory pool and STA_REC + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + // <2> Mailbox Initialization + mboxInitialize(prAdapter); + + // <3> Timer Initialization + cnmTimerInitialize(prAdapter); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function reset some specific system service, +* such as STA-REC +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicResetSystemService ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUninitSystemService ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicInitMGMT ( + IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo + ) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisInitializeConnectionSettings(prAdapter, prRegInfo); + aisFsmInit(prAdapter); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUninitMGMT ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + +#if CFG_SUPPORT_SWCR + swCrDebugUninit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* AIS Module - unintiailization */ + aisFsmUninit(prAdapter); + + /* SCN Module - unintiailization */ + scnUninit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + + return; +} + + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to enable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicEnableClockGating ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if(prAdapter->fgIsClockGatingEnabled == TRUE) { + return WLAN_STATUS_SUCCESS; + } + else { + nicSetSwIntr(prAdapter, REQ_GATING_ENABLE_H2D_INT); + + i = 0; + while(i < GATING_CONTROL_POLL_LIMIT) { + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + return WLAN_STATUS_FAILURE; + } + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if(u4WHISR & ACK_GATING_ENABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = TRUE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to disable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicDisableClockGating ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if(prAdapter->fgIsClockGatingEnabled == FALSE) { + return WLAN_STATUS_SUCCESS; + } + else { + nicSetSwIntr(prAdapter, REQ_GATING_DISABLE_H2D_INT); + + i = 0; + while(i < GATING_CONTROL_POLL_LIMIT) { + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + return WLAN_STATUS_FAILURE; + } + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if(u4WHISR & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; + } +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param rMacAddr BSSID +* @param prSsid Pointer to SSID +* @param u4Privacy Privacy settings (0: Open / 1: WEP/WPA/WPA2 enabled) +* @param rRssi Received Strength (-10 ~ -200 dBm) +* @param eNetworkType Network Type (a/b/g) +* @param prConfiguration Network Parameter +* @param eOpMode Infra/Ad-Hoc +* @param rSupportedRates Supported basic rates +* @param u2IELength IE Length +* @param pucIEBuf Pointer to Information Elements(IEs) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicAddScanResult ( + IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_32 u4Privacy, + IN PARAM_RSSI rRssi, + IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, + IN P_PARAM_802_11_CONFIG_T prConfiguration, + IN ENUM_PARAM_OP_MODE_T eOpMode, + IN PARAM_RATES_EX rSupportedRates, + IN UINT_16 u2IELength, + IN PUINT_8 pucIEBuf + ) +{ + BOOLEAN bReplace; + UINT_32 i; + UINT_32 u4IdxWeakest = 0; + PARAM_RSSI rWeakestRssi; + UINT_32 u4BufferSize; + + ASSERT(prAdapter); + + rWeakestRssi = (PARAM_RSSI)INT_MAX; + u4BufferSize = sizeof(prAdapter->rWlanInfo.aucScanIEBuf) / sizeof(prAdapter->rWlanInfo.aucScanIEBuf[0]); + + bReplace = FALSE; + + // decide to replace or add + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + // find weakest entry && not connected one + if(UNEQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, prAdapter->rWlanInfo.rCurrBssId.arMacAddress) + && prAdapter->rWlanInfo.arScanResult[i].rRssi < rWeakestRssi) { + u4IdxWeakest = i; + rWeakestRssi = prAdapter->rWlanInfo.arScanResult[i].rRssi; + } + + if(prAdapter->rWlanInfo.arScanResult[i].eOpMode == eOpMode && + EQUAL_MAC_ADDR(&(prAdapter->rWlanInfo.arScanResult[i].arMacAddress), rMacAddr) && + (EQUAL_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, + prSsid->u4SsidLen) + || prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen == 0)) { + // replace entry + bReplace = TRUE; + + // free IE buffer then zero + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + // then fill buffer + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, + prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, + sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, + sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32)u2IELength; + + // IE - allocate buffer and update pointer + if(u2IELength > 0) { + if(ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(&(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } + else { + // buffer is not enough + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + break; + } + } + + if (bReplace == FALSE) { + if (prAdapter->rWlanInfo.u4ScanResultNum < (CFG_MAX_NUM_BSS_LIST - 1)) { + i = prAdapter->rWlanInfo.u4ScanResultNum; + + // zero + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + // then fill buffer + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, + prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, + sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, + sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32)u2IELength; + + // IE - allocate buffer and update pointer + if(u2IELength > 0) { + if(ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(&(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } + else { + // buffer is not enough + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + prAdapter->rWlanInfo.u4ScanResultNum++; + } + else if(rWeakestRssi != (PARAM_RSSI)INT_MAX) { + // replace weakest one + i = u4IdxWeakest; + + // free IE buffer then zero + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + // then fill buffer + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, + prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, + sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, + sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32)u2IELength; + + if(u2IELength > 0) { + // IE - allocate buffer and update pointer + if(ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(&(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } + else { + // buffer is not enough + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to free IE buffer for dedicated scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4Idx Index of Scan Result +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicFreeScanResultIE ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Idx + ) +{ + UINT_32 i; + PUINT_8 pucPivot, pucMovePivot; + UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; + + ASSERT(prAdapter); + ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); + + if(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 + || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { + return; + } + + u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); + + pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; + pucMovePivot = (PUINT_8)((UINT_32)(prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); + + u4ReserveSize = ((UINT_32)pucPivot) - (UINT_32)(&(prAdapter->rWlanInfo.aucScanIEBuf[0])); + u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; + + // 1. rest of buffer to move forward + kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); + + // 1.1 modify pointers + for(i = 0 ; i < prAdapter->rWlanInfo.u4ScanResultNum ; i++) { + if(i != u4Idx) { + if(prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { + prAdapter->rWlanInfo.apucScanResultIEs[i] = + (PUINT_8)((UINT_32)(prAdapter->rWlanInfo.apucScanResultIEs[i]) - u4FreeSize); + } + } + } + + // 1.2 reset the freed one + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + // 2. reduce IE buffer usage + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to hack parameters for WLAN TABLE for +* fixed rate settings +* +* @param prAdapter Pointer to the Adapter structure. +* @param eRateSetting +* @param pu2DesiredNonHTRateSet, +* @param pu2BSSBasicRateSet, +* @param pucMcsSet +* @param pucSupMcs32 +* @param pu2HtCapInfo +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams ( + IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, + IN PUINT_8 pucSupMcs32, + IN PUINT_16 pu2HtCapInfo + ) +{ + ASSERT(prAdapter); + ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); + + switch(prAdapter->rWifiVar.eRateSetting) { + case FIXED_RATE_1M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; + *pu2BSSBasicRateSet = RATE_SET_BIT_1M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_2M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; + *pu2BSSBasicRateSet = RATE_SET_BIT_2M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_5_5M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; + *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_11M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; + *pu2BSSBasicRateSet = RATE_SET_BIT_11M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_6M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; + *pu2BSSBasicRateSet = RATE_SET_BIT_6M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_9M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; + *pu2BSSBasicRateSet = RATE_SET_BIT_9M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_12M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; + *pu2BSSBasicRateSet = RATE_SET_BIT_12M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_18M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; + *pu2BSSBasicRateSet = RATE_SET_BIT_18M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_24M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; + *pu2BSSBasicRateSet = RATE_SET_BIT_24M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_36M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; + *pu2BSSBasicRateSet = RATE_SET_BIT_36M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_48M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; + *pu2BSSBasicRateSet = RATE_SET_BIT_48M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_54M: + if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_ERP) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + } + else if((*pucDesiredPhyTypeSet) | PHY_TYPE_BIT_OFDM) { + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + } + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; + *pu2BSSBasicRateSet = RATE_SET_BIT_54M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_MCS0_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS1_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS2_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS3_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS4_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS5_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS6_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS7_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS0_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS1_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS2_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS3_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS4_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS5_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS6_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS7_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS0_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS1_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS2_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS3_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS4_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS5_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS6_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS7_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS32_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_SHORT_GI_40M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS0_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS1_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS2_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS3_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS4_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS5_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS6_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS7_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS32_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M + | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_40M); + break; + + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to write the register +* +* @param u4Address Register address +* u4Value the value to be written +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicWriteMcr ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Address, + IN UINT_32 u4Value + ) +{ + CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, + NULL, + 0 + ); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to modify the auto rate parameters +* +* @param u4ArSysParam0 see description below +* u4ArSysParam1 +* u4ArSysParam2 +* u4ArSysParam3 +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* ArSysParam0[0:3] -> auto rate version (0:disable 1:version1 2:version2) +* ArSysParam0[4:5]-> auto bw version (0:disable 1:version1 2:version2) +* ArSysParam0[6:7]-> auto gi version (0:disable 1:version1 2:version2) +* ArSysParam0[8:15]-> HT rate clear mask +* ArSysParam0[16:31]-> Legacy rate clear mask +* ArSysParam1[0:7]-> Auto Rate check weighting window +* ArSysParam1[8:15]-> Auto Rate v1 Force Rate down +* ArSysParam1[16:23]-> Auto Rate v1 PerH +* ArSysParam1[24:31]-> Auto Rate v1 PerL +* +* Examples +* ArSysParam0 = 1, +* Enable auto rate version 1 +* +* ArSysParam0 = 983041, +* Enable auto rate version 1 +* Remove CCK 1M, 2M, 5.5M, 11M +* +* ArSysParam0 = 786433 +* Enable auto rate version 1 +* Remove CCK 5.5M 11M +*/ +/*----------------------------------------------------------------------------*/ + + +WLAN_STATUS +nicRlmArUpdateParms( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, + IN UINT_32 u4ArSysParam2, + IN UINT_32 u4ArSysParam3 + ) +{ + UINT_8 ucArVer,ucAbwVer,ucAgiVer; + UINT_16 u2HtClrMask; + UINT_16 u2LegacyClrMask; + UINT_8 ucArCheckWindow; + UINT_8 ucArPerL; + UINT_8 ucArPerH; + UINT_8 ucArPerForceRateDownPer; + + ucArVer = (UINT_8)(u4ArSysParam0 & BITS(0,3)); + ucAbwVer = (UINT_8)((u4ArSysParam0 & BITS(4,5)) >>4); + ucAgiVer = (UINT_8)((u4ArSysParam0 & BITS(6,7)) >>6); + u2HtClrMask = (UINT_16) ((u4ArSysParam0 & BITS(8,15)) >> 8); + u2LegacyClrMask = (UINT_16) ((u4ArSysParam0 & BITS(16,31)) >> 16); + +#if 0 + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0,7)); + ucArPerForceRateDownPer = (UINT_8) ((u4ArSysParam1 & BITS(8,15)>>8)); + ucArPerH = (UINT_8) ((u4ArSysParam1 & BITS(16,23)) >>16); + ucArPerL = (UINT_8) ((u4ArSysParam1 & BITS(24,31)) >>24); +#endif + + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0,7)); + ucArPerForceRateDownPer = (UINT_8) (((u4ArSysParam1>>8) & BITS(0,7))); + ucArPerH = (UINT_8) (((u4ArSysParam1>>16) & BITS(0,7))); + ucArPerL = (UINT_8) (((u4ArSysParam1>>24) & BITS(0,7))); + + + DBGLOG(INIT, INFO, ("ArParam %u %u %u %u\n", u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3)); + DBGLOG(INIT, INFO, ("ArVer %u AbwVer %u AgiVer %u\n", ucArVer, ucAbwVer, ucAgiVer)); + DBGLOG(INIT, INFO, ("HtMask %x LegacyMask %x\n", u2HtClrMask, u2LegacyClrMask)); + DBGLOG(INIT, INFO, ("CheckWin %u RateDownPer %u PerH %u PerL %u\n", ucArCheckWindow, ucArPerForceRateDownPer, ucArPerH, ucArPerL)); + +#define SWCR_DATA_ADDR(MOD,ADDR) (0x90000000+(MOD<<8)+(ADDR)) +#define SWCR_DATA_CMD(CATE,WRITE,INDEX,OPT0,OPT1) ( (CATE<<24) | (WRITE<<23) | (INDEX<<16) | (OPT0 <<8) | OPT1 ) +#define SWCR_DATA0 0x0 +#define SWCR_DATA1 0x4 +#define SWCR_DATA2 0x8 +#define SWCR_DATA3 0xC +#define SWCR_DATA4 0x10 +#define SWCR_WRITE 1 +#define SWCR_READ 0 + + if(ucArVer > 0) { + /* dummy = WiFi.WriteMCR(&h90000104, &h00000001) */ + /* dummy = WiFi.WriteMCR(&h90000100, &h00850000)*/ + + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),1); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,5,0,0)); + } + else { + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),0); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,5,0,0)) ; + } + + /* ucArVer 0: none 1:PER 2:Rcpi */ + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArVer); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,7,0,0)); + + /* Candidate rate Ht mask */ + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),u2HtClrMask); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x1c,0,0)); + + /* Candidate rate legacy mask */ + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),u2LegacyClrMask); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x1d,0,0)); + +#if 0 + if(ucArCheckWindow!=0) { + /* TX DONE MCS INDEX CHECK STA RATE DOWN TH */ + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArCheckWindow); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x14,0,0)); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArCheckWindow); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0xc,0,0)); + } + + if(ucArPerForceRateDownPer !=0) { + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArPerForceRateDownPer); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x18,0,0)); + } + if(ucArPerH !=0) { + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArPerH); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x1,0,0)); + } + if(ucArPerL !=0) { + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA1),ucArPerL); + nicWriteMcr (prAdapter, SWCR_DATA_ADDR(1/*MOD*/,SWCR_DATA0),SWCR_DATA_CMD(0,SWCR_WRITE,0x2,0,0)); + } +#endif + + + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to enable roaming +* +* @param u4EnableRoaming +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* u4EnableRoaming -> Enable Romaing +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRoamingUpdateParams( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4EnableRoaming + ) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsEnableRoaming = ((u4EnableRoaming>0)?(TRUE):(FALSE)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicPrintFirmwareAssertInfo( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4MailBox0, u4MailBox1; + UINT_32 line = 0; + UINT_8 aucAssertFile[7]; + UINT_32 u4ChipId; + +#if CFG_SDIO_INTR_ENHANCE + u4MailBox0 = prAdapter->prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prSDIOCtrl->u4RcvMailbox1; +#else + nicGetMailbox(prAdapter, 0, &u4MailBox0); + nicGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + +#if defined(MT6620) + u4ChipId = 6620; +#elif defined(MT5931) + u4ChipId = 5931; +#elif defined(MT6628) + u4ChipId = 6628; +#endif + + kalPrint("\n[MT%ld][wifi][Firmware] Assert at \"%s\" #%ld\n\n", + u4ChipId, + aucAssertFile, + line); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN P_EVENT_LINK_QUALITY prEventLinkQuality + ) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventLinkQuality); + + switch(eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if(prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* check is to prevent RSSI to be updated by incorrect initial RSSI from hardware */ + /* buffer statistics for further query */ + if(prAdapter->fgIsLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateRSSI(prAdapter, eNetTypeIdx, prEventLinkQuality->cRssi, prEventLinkQuality->cLinkQuality); + } + + if(prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, eNetTypeIdx, prEventLinkQuality->u2LinkSpeed); + } + } + break; +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + if (prAdapter->fgIsP2pLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + P_EVENT_LINK_QUALITY_EX prEventLQEx = (P_EVENT_LINK_QUALITY_EX)prEventLinkQuality; + + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, prEventLQEx->cRssiP2P, prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update RSSI and Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateRSSI( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN INT_8 cRssi, + IN INT_8 cLinkQuality + ) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch(eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if(prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + prAdapter->fgIsLinkQualityValid = TRUE; + prAdapter->rLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.cRssi = cRssi; + prAdapter->rLinkQuality.cLinkQuality = cLinkQuality; + + /* indicate to glue layer */ + kalUpdateRSSI(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_AIS_INDEX, + prAdapter->rLinkQuality.cRssi, + prAdapter->rLinkQuality.cLinkQuality); + } + + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + prAdapter->fgIsP2pLinkQualityValid = TRUE; + prAdapter->rP2pLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rP2pLinkQuality.cRssi= cRssi; + prAdapter->rP2pLinkQuality.cLinkQuality= cLinkQuality; + + kalUpdateRSSI(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_P2P_INDEX, + cRssi, + cLinkQuality); + break; +#endif +#endif + default: + break; + + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN UINT_16 u2LinkSpeed + ) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch(eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if(prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + + return; +} + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS +nicUpdateRddTestMode( + IN P_ADAPTER_T prAdapter, + IN P_CMD_RDD_CH_T prRddChParam + ) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + +// aisFsmScanRequest(prAdapter, NULL); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_RDD_CH_T), + (PUINT_8)prRddChParam, + NULL, + 0); +} +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c new file mode 100755 index 000000000000..c9743946d88c --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c @@ -0,0 +1,1651 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#1 $ +*/ + +/*! \file nic_cmd_event.c + \brief Callback functions for Command packets. + + Various Event packet handlers which will be setup in the callback function of + a command packet. +*/ + + + +/* +** $Log: nic_cmd_event.c $ + * + * 04 10 2012 yuche.tsai + * NULL + * Update address for wifi direct connection issue. + * + * 06 15 2011 cm.chang + * [WCXRP00000785] [MT6620 Wi-Fi][Driver][FW] P2P/BOW MAC address is XOR with AIS MAC address + * P2P/BOW mac address XOR with local bit instead of OR + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 02 24 2011 cp.wu + * [WCXRP00000493] [MT6620 Wi-Fi][Driver] Do not indicate redundant disconnection to host when entering into RF test mode + * only indicate DISCONNECTION to host when entering RF test if necessary (connected -> disconnected cases) + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 12 01 2010 cp.wu + * [WCXRP00000223] MT6620 Wi-Fi][Driver][FW] Adopt NVRAM parameters when enter/exit RF test mode + * reload NVRAM settings before entering RF test mode and leaving from RF test mode. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 15 2010 yuche.tsai + * NULL + * Start to test AT GO only when P2P state is not IDLE. + * + * 09 09 2010 yuche.tsai + * NULL + * Add AT GO Test mode after MAC address available. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 11 2010 yuche.tsai + * NULL + * Add support for P2P Device Address query from FW. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 08 02 2010 cp.wu + * NULL + * reset FSMs before entering RF test mode. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. + * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change upon request: indicate as disconnected in driver domain when leaving from RF test mode + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not clear scanning list array after disassociation + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. + * 2) finish statistics OIDs + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glude code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sync statistics data structure definition with firmware implementation + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * limit RSSI return value to microsoft defined range. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * block until firmware finished RF test enter/leave then indicate completion to upper layer + * + * 01 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when entering RF test mode and leaving from RF test mode, wait for W_FUNC_RDY bit to be asserted forever until it is set or card is removed. + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * * 4. correct some HAL implementation + * + * 01 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * * OID_802_11_RSSI, + * * * * * OID_802_11_RSSI_TRIGGER, + * * * * * OID_802_11_STATISTICS, + * * * * * OID_802_11_DISASSOCIATE, + * * * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:47:47 GMT mtk02752 +** only handle MCR read when accessing FW domain register +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 17:37:28 GMT mtk02752 +** * refine nicCmdEventQueryMcrRead +** + add TxStatus/RxStatus for RF test QueryInformation OIDs +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 22:05:45 GMT mtk02752 +** kalOidComplete() will decrease i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-01 23:02:57 GMT mtk02752 +** remove unnecessary spin locks +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-01 22:51:18 GMT mtk02752 +** maintein i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-30 10:55:03 GMT mtk02752 +** modify for compatibility +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 14:46:32 GMT mtk02752 +** add another version of command-done handler upon new event structure +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:33 GMT mtk01461 +** Add comment +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 19:32:42 GMT mtk01461 +** Add nicCmdEventSetCommon() for general set OID +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:35 GMT mtk01461 +** Command Done Handler +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +VOID +nicCmdEventQueryMcrRead ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MCR_RW_STRUC_T prMcrRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (P_CMD_ACCESS_REG)(pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T); + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_T) prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + + +VOID +nicCmdEventQuerySwCtrlRead ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_SW_CTRL_STRUC_T prSwCtrlInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T)(pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_T) prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + + + +VOID +nicCmdEventSetCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, + WLAN_STATUS_SUCCESS); + } + + return; +} + +VOID +nicCmdEventSetDisassociate ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_SUCCESS); + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return; +} + +VOID +nicCmdEventSetIpAddress ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(IPV4_NETWORK_ADDRESS) ; + + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP)), + WLAN_STATUS_SUCCESS); + } + + return; +} + +VOID +nicCmdEventQueryRfTestATInfo( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (P_EVENT_TEST_STATUS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prQueryBuffer, prTestStatus, sizeof(EVENT_TEST_STATUS)); + + u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); + + /* Update Query Infomation Length */ + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } + + return; +} + +VOID +nicCmdEventQueryLinkQuality( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + PARAM_RSSI rRssi, *prRssi; + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY)pucEventBuf; + + rRssi = (PARAM_RSSI)prLinkQuality->cRssi; // ranged from (-128 ~ 30) in unit of dBm + + if(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if(rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if(rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } + else { + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); + u4QueryInfoLen = sizeof(PARAM_RSSI); + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is in response of OID_GEN_LINK_SPEED query request +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the pending command info +* @param pucEventBuf +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicCmdEventQueryLinkSpeed( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (PUINT_32)(prCmdInfo->pvInformationBuffer); + + if(prLinkQuality->u2LinkSpeed == 0) { + *pu4LinkSpeed = 10000; /* 10K * 100bps = 1Mbps */ + } + else { + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + } + + u4QueryInfoLen = sizeof(UINT_32); + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryStatistics( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) prCmdInfo->pvInformationBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount + = prEventStatistics->rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount + = prEventStatistics->rMulticastTransmittedFrameCount; + prStatistics->rFailedCount + = prEventStatistics->rFailedCount; + prStatistics->rRetryCount + = prEventStatistics->rRetryCount; + prStatistics->rMultipleRetryCount + = prEventStatistics->rMultipleRetryCount; + prStatistics->rRTSSuccessCount + = prEventStatistics->rRTSSuccessCount; + prStatistics->rRTSFailureCount + = prEventStatistics->rRTSFailureCount; + prStatistics->rACKFailureCount + = prEventStatistics->rACKFailureCount; + prStatistics->rFrameDuplicateCount + = prEventStatistics->rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount + = prEventStatistics->rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount + = prEventStatistics->rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount + = prEventStatistics->rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart + = 0; + prStatistics->rTKIPICVErrors.QuadPart + = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart + = 0; + prStatistics->rTKIPReplays.QuadPart + = 0; + prStatistics->rCCMPFormatErrors.QuadPart + = 0; + prStatistics->rCCMPReplays.QuadPart + = 0; + prStatistics->rCCMPDecryptErrors.QuadPart + = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart + = 0; + prStatistics->rWEPUndecryptableCount.QuadPart + = 0; + prStatistics->rWEPICVErrorCount.QuadPart + = 0; + prStatistics->rDecryptSuccessCount.QuadPart + = 0; + prStatistics->rDecryptFailureCount.QuadPart + = 0; + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + +VOID +nicCmdEventEnterRfTest( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + // [driver-land] + prAdapter->fgTestMode = TRUE; + + // 0. always indicate disconnection + if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + + // 1. Remove pending TX + nicTxRelease(prAdapter); + + // 1.1 clear pending Security / Management Frames + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + // 1.2 clear pending TX packet queued in glue layer + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + // 2. Reset driver-domain FSMs + nicUninitMGMT(prAdapter); + + nicResetSystemService(prAdapter); + nicInitMGMT(prAdapter, NULL); + + // 3. Disable Interrupt + HAL_INTR_DISABLE(prAdapter); + + // 4. Block til firmware completed entering into RF test mode + kalMsleep(500); + while(1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + else + kalMsleep(10); + } + + // 5. Clear Interrupt Status + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if(HAL_IS_TX_DONE_INTR(u4WHISR)) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + } + + // 6. Reset TX Counter + nicTxResetResource(prAdapter); + + // 7. Re-enable Interrupt + HAL_INTR_ENABLE(prAdapter); + + // 8. completion indication + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + +#if CFG_SUPPORT_NVRAM + // 9. load manufacture data + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + + return; +} + +VOID +nicCmdEventLeaveRfTest( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + // 1. Disable Interrupt + HAL_INTR_DISABLE(prAdapter); + + // 2. Block til firmware completed leaving from RF test mode + kalMsleep(500); + while(1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + else { + kalMsleep(10); + } + } + + // 3. Clear Interrupt Status + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if(HAL_IS_TX_DONE_INTR(u4WHISR)) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + } + + // 4. Reset TX Counter + nicTxResetResource(prAdapter); + + // 5. Re-enable Interrupt + HAL_INTR_ENABLE(prAdapter); + + // 6. set driver-land variable + prAdapter->fgTestMode = FALSE; + + // 7. completion indication + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + return; +} + +VOID +nicCmdEventQueryAddress( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG)(pucEventBuf); + + // copy to adapter + kalMemCopy(&(prAdapter->rMyMacAddr), &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + kalMemCopy(prCmdInfo->pvInformationBuffer, &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + u4QueryInfoLen = MAC_ADDR_LEN; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + //4 <3> Update new MAC address and all 3 networks + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prAdapter->rMyMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucDeviceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucInterfaceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucOwnMacAddr, + prAdapter->rMyMacAddr); + +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); +#endif + +#if CFG_TEST_WIFI_DIRECT_GO + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_IDLE) { + wlanEnableP2pFunction(prAdapter); + + wlanEnableATGO(prAdapter); + } +#endif + + kalUpdateMACAddress(prAdapter->prGlueInfo, prAdapter->rWifiVar.aucMacAddress); + + return; +} + +VOID +nicCmdEventQueryMcastAddr( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR)(pucEventBuf); + + u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; + + // buffer length check + if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); + } + else { + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventMacMcastAddr->arAddress, + prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } +} + +VOID +nicCmdEventQueryEepromRead( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_EEPROM_RW_STRUC_T prEepromRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_ACCESS_EEPROM prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM)(pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T); + + prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_T) prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (UINT_8)(prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + + +VOID +nicCmdEventSetMediaStreamMode( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Infomation Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? + ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&rParamMediaStreamIndication, + sizeof(PARAM_MEDIA_STREAMING_INDICATION)); +} + + +/* Statistics responder */ +VOID +nicCmdEventQueryXmitOk( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rTransmittedFragmentCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rTransmittedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryRecvOk( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rReceivedFragmentCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rReceivedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + +VOID +nicCmdEventQueryXmitError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryRecvError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + // @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + // @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryRecvNoBuffer( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = 0; // @FIXME? + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; //@FIXME? + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryRecvCrcError( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryRecvErrorAlignment( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) 0; //@FIXME + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; //@FIXME + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryXmitOneCollision( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) (prEventStatistics->rMultipleRetryCount.QuadPart - prEventStatistics->rRetryCount.QuadPart); + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) (prEventStatistics->rMultipleRetryCount.QuadPart - prEventStatistics->rRetryCount.QuadPart); + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryXmitMoreCollisions( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rMultipleRetryCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rMultipleRetryCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +VOID +nicCmdEventQueryXmitMaxCollisions( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS)pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if(prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } + else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command by OID/ioctl has been timeout +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicOidCmdTimeoutCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + ASSERT(prAdapter); + + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a generic command timeout handler +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicCmdTimeoutCommon ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + ASSERT(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for entering RF test has +* failed sending due to timeout (highly possibly by firmware crash) +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicOidCmdEnterRFTestTimeout ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo + ) +{ + ASSERT(prAdapter); + + // 1. Remove pending TX frames + nicTxRelease(prAdapter); + + // 1.1 clear pending Security / Management Frames + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + // 1.2 clear pending TX packet queued in glue layer + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + // 2. indiate for OID failure + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for memory dump has +* replied a event. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicCmdEventQueryMemDump ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf + ) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MEM_DUMP_STRUC_T prMemDumpInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_DUMP_MEM_T prEventDumpMem; + static UINT_8 aucPath[256]; + static UINT_32 u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + //4 <2> Update information of OID + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (P_EVENT_DUMP_MEM_T)(pucEventBuf); + + u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUC_T); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUC_T) prCmdInfo->pvInformationBuffer; + prMemDumpInfo->u4Address = prEventDumpMem->u4Address; + prMemDumpInfo->u4Length = prEventDumpMem->u4Length; + prMemDumpInfo->u4RemainLength = prEventDumpMem->u4RemainLength; + prMemDumpInfo->ucFragNum = prEventDumpMem->ucFragNum; + +#if 0 + do{ + UINT_32 i = 0; + printk("Rx dump address 0x%X, Length %d, FragNum %d, remain %d\n", + prEventDumpMem->u4Address, + prEventDumpMem->u4Length, + prEventDumpMem->ucFragNum, + prEventDumpMem->u4RemainLength); +#if 0 + for(i = 0; i < prEventDumpMem->u4Length; i++) { + printk("%02X ", prEventDumpMem->aucBuffer[i]); + if(i % 32 == 31) { + printk("\n"); + } + } +#endif + }while(FALSE); +#endif + + if(prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); + sprintf(aucPath, "/sdcard/dump_%ld_0x%08lX_%ld.hex", + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + kalWriteToFile(aucPath, FALSE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } + else { + /* Append current memory dump to the hex file */ + kalWriteToFile(aucPath, TRUE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } + + if(prEventDumpMem->u4RemainLength == 0 || + prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + *((PUINT_32)prCmdInfo->pvInformationBuffer) = u4CurTimeTick; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + else { + /* The memory dump request is not finished, Send next command*/ + wlanSendMemDumpCmd( + prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); + } + } + + return; + +} + + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c new file mode 100755 index 000000000000..f469057da479 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c @@ -0,0 +1,802 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_pwr_mgt.c#1 $ +*/ + +/*! \file "nic_pwr_mgt.c" + \brief In this file we define the STATE and EVENT for Power Management FSM. + + The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter + ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail + description. +*/ + + + +/* +** $Log: nic_pwr_mgt.c $ + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 29 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * fix for compilation error when applied with FW_DOWNLOAD = 0 + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 04 13 2011 cp.wu + * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete + * refine for MT5931/MT6620 logic separation. + * + * 04 13 2011 cp.wu + * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete + * bugfix: firmware download procedure for ACPI state transition is not complete. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * check success or failure for setting fw-own + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 30 2010 cp.wu + * NULL + * reset ACPI power state before waking up MT6620 Wi-Fi firmware. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll + * 2) correct address list parsing + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sleepy notify is only used for sleepy state, + * while wake-up state is automatically set when host needs to access device + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct hibernation problem. + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when acquiring driver-own, wait for up to 8 seconds. + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove redundant firmware image unloading + * * 2) use compile-time macros to separate logic related to accquiring own + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * are now handled in glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct typo. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-13 21:59:15 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-09-09 17:26:36 GMT mtk01084 +** remove CMD52 access +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-18 14:50:29 GMT mtk01084 +** modify lines in nicpmSetDriverOwn() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:55:37 GMT mtk01084 +** modify nicpmSetDriverOwn() +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:33:00 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:32 GMT mtk01084 +** Initial version +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/extern BOOLEAN fgIsResetting; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicpmSetFWOwn ( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnableGlobalInt + ) +{ + UINT_32 u4RegValue; + + ASSERT(prAdapter); + + if(prAdapter->fgIsFwOwn == TRUE) { + return; + } + else { + if(nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + // pending interrupts + return; + } + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } + else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + if(u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + // if set firmware own not successful (possibly pending interrupts), + // indicate an own clear event + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + + return; + } + + prAdapter->fgIsFwOwn = TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +nicpmSetDriverOwn ( + IN P_ADAPTER_T prAdapter + ) +{ +#define LP_OWN_BACK_TOTAL_DELAY_MS 8192 //exponential of 2 +#define LP_OWN_BACK_LOOP_DELAY_MS 1 //exponential of 2 +#define LP_OWN_BACK_CLR_OWN_ITERATION 256 //exponential of 2 + + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick, u4RegValue = 0; + + ASSERT(prAdapter); + + if(prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + u4CurrTick = kalGetTimeTick(); + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + prAdapter->fgIsFwOwn = FALSE; + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || (kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS + ||fgIsResetting ==TRUE) { + //ERRORLOG(("LP cannot be own back (for %ld ms)", kalGetTimeTick() - u4CurrTick)); + fgStatus = FALSE; + break; + } + else { + if((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { + /* Software get LP ownership - per 256 iterations */ + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + } + + /* Delay for LP engine to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + i++; + } + } + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set ACPI power mode to D0. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +nicpmSetAcpiPowerD0 ( + IN P_ADAPTER_T prAdapter + ) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Value = 0, u4WHISR = 0; + UINT_8 aucTxCount[8]; + UINT_32 i; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwImgLength, u4FwLoadAddr, u4ImgSecSize; + PVOID prFwMappingHandle; + PVOID pvFwImageMapFile = NULL; + #if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); + #endif +#endif + + DEBUGFUNC("nicpmSetAcpiPowerD0"); + + ASSERT(prAdapter); + + do { + /* 0. Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + +#if defined(MT6620) || defined(MT6628) + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + #if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); + #endif + + /* 2. Initialize the Adapter */ + if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) { + DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + #if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength); + if(!prFwMappingHandle) { + DBGLOG(INIT, ERROR,("Fail to load FW image from file!\n")); + pvFwImageMapFile = NULL; + } + + #if defined(MT6620) || defined(MT6628) + if (pvFwImageMapFile) { + /* 3.1 disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 3.2 Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3.3 FW download here */ + u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo); + + #if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + // 3a. parse file header for decision of divided firmware download or not + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T)pvFwImageMapFile; + + if(prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8)pvFwImageMapFile + u4CRCOffset, u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } + else { + fgValidHead = FALSE; + } + + /* 3b. engage divided firmware downloading */ + if(fgValidHead == TRUE) { + for(i = 0 ; i < prFwHead->u4NumOfEntries ; i++) { + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if(wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8)pvFwImageMapFile + prFwHead->arSection[i].u4Offset) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + } + #else + for(j = 0 ; j < prFwHead->arSection[i].u4Length ; j += CMD_PKT_SIZE_FOR_IMAGE) { + if(j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + if(wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + prFwHead->arSection[i].u4Offset + j) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + #endif + /* escape from loop if any pending error occurs */ + if(u4Status == WLAN_STATUS_FAILURE) { + break; + } + } + } + else + #endif + #if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if(wlanImageSectionDownloadAggregated(prAdapter, + u4FwLoadAddr, + u4FwImgLength, + (PUINT_8)pvFwImageMapFile) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + } + #else + for (i = 0; i < u4FwImgLength ; i += CMD_PKT_SIZE_FOR_IMAGE) { + if(i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImgLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImgLength - i; + + if(wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("wlanImageSectionDownload failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + #endif + + if(u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + break; + } + + #if !CFG_ENABLE_FW_DOWNLOAD_ACK + // Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response + if(wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } + #endif + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + } + else { + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 4. send Wi-Fi Start command */ + #if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, + TRUE, + kalGetFwStartAddress(prAdapter->prGlueInfo)); + #else + wlanConfigWifiFunc(prAdapter, + FALSE, + 0); + #endif + + #elif defined(MT5931) + if (pvFwImageMapFile) { + DBGLOG(INIT, TRACE, ("Download Address: 0x%08X\n", kalGetFwLoadAddress(prAdapter->prGlueInfo))); + DBGLOG(INIT, TRACE, ("Firmware Length: 0x%08X\n", u4FwImgLength)); + + do { + /* 1.0 whole-chip reset except HIFSYS */ + HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_CHIP_RST); + HAL_MCR_WR(prAdapter, MCR_WMCSR, 0); + + /* 1.1 wait for INIT_RDY */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_INI_RDY) { + DBGLOG(INIT, TRACE, ("INIT-RDY detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for Init Ready bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + /* 1.2 set KSEL/FLEN */ + HAL_MCR_WR(prAdapter, MCR_FWCFG, u4FwImgLength >> 6); + + /* 1.3 enable FWDL_EN */ + HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_FWDLEN); + + /* 1.4 wait for PLL_RDY */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_PLLRDY) { + DBGLOG(INIT, TRACE, ("PLL-RDY detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for PLL Ready bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + /* 2.1 turn on HIFSYS firmware download mode */ + HAL_MCR_WR(prAdapter, MCR_FWDLSR, FWDLSR_FWDL_MODE); + + /* 2.2 set starting address */ + u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo); + HAL_MCR_WR(prAdapter, MCR_FWDLDSAR, u4FwLoadAddr); + + /* 3. upload firmware */ + for (i = 0; i < u4FwImgLength ; i += CMD_PKT_SIZE_FOR_IMAGE) { + if(i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImgLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImgLength - i; + + if(wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("Firmware scatter download failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + + /* 4.1 poll FWDL_OK & FWDL_FAIL bits */ + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value); + + if (u4Value & WMCSR_DL_OK) { + DBGLOG(INIT, TRACE, ("DL_OK detected\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || (u4Value & WMCSR_DL_FAIL)) { + DBGLOG(INIT, ERROR, ("DL_FAIL detected: 0x%08X\n", u4Value)); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for DL_OK/DL_FAIL bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + + /* 4.2 turn off HIFSYS download mode */ + HAL_MCR_WR(prAdapter, MCR_FWDLSR, 0); + + } while (FALSE); + } + else { + DBGLOG(INIT, ERROR, ("No Firmware found!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + #endif + #endif + + /* 5. check Wi-Fi FW asserts ready bit */ + DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Waiting for Ready bit..\n")); + i = 0; + while(1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(INIT, TRACE, ("Ready bit asserted\n")); + break; + } + else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(INIT, ERROR, ("Waiting for Ready bit: Timeout\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } + else { + i++; + kalMsleep(10); + } + } + +#if defined(MT5931) + // Acquire LP-OWN + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + #if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); + #endif + + /* 2. Initialize the Adapter */ + if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) { + DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n")); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + if(u4Status == WLAN_STATUS_SUCCESS) { + // 6.1 reset interrupt status + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if(HAL_IS_TX_DONE_INTR(u4WHISR)) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + } + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6.5 indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, NULL); + + } while(FALSE); + + if(u4Status != WLAN_STATUS_SUCCESS) { + return FALSE; + } + else { + return TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is used to set ACPI power mode to D3. +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +nicpmSetAcpiPowerD3 ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* 1. MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* 2. Disable Interrupt */ + nicDisableInterrupt(prAdapter); + + /* 3. emit CMD_NIC_POWER_CTRL command packet */ + wlanSendNicPowerCtrlCmd(prAdapter, 1); + + /* 4. Clear Interrupt Status */ + i = 0; + while(i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 5. Remove pending TX */ + nicTxRelease(prAdapter); + + // 5.1 clear pending Security / Management Frames + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + // 5.2 clear pending TX packet queued in glue layer + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 6. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + + /* 7. Set variables */ + prAdapter->rAcpiState = ACPI_STATE_D3; + + return TRUE; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c new file mode 100755 index 000000000000..596d8defd852 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c @@ -0,0 +1,3528 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#3 $ +*/ + +/*! \file nic_rx.c + \brief Functions that provide many rx-related functions + + This file includes the functions used to process RFB and dispatch RFBs to + the appropriate related rx functions for protocols. +*/ + + + +/* +** $Log: nic_rx.c $ +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 14 2012 cp.wu + * NULL + * remove another assertion by error message dump + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 09 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for beacon timeout and sta aging timeout. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 08 26 2011 cp.wu + * [WCXRP00000958] [MT6620 Wi-Fi][Driver] Extend polling timeout from 25ms to 1sec due to RF calibration might took up to 600ms + * extend polling RX response timeout period from 25ms to 1000ms. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 27 2011 cp.wu + * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently availble RX counter and QUE_MGT used count + * correct comment. + * + * 07 27 2011 cp.wu + * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently availble RX counter and QUE_MGT used count + * take use of QUE_MGT exported function to estimate currently RX buffer usage count. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support for GO. + * + * 04 01 2011 tsaiyuan.hsu + * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues + * fix the klocwork issues, 57500, 57501, 57502 and 57503. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 18 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the Anti_piracy check at driver . + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA module. + * Remove Station Record after Aging timeout. + * + * 02 10 2011 cp.wu + * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers + * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add MLME deauthentication support for Hot-Spot mode. + * + * 02 09 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Adjust variable order. + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Remove comments. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * update beacon for NoA + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 20 2010 wh.su + * NULL + * add a cmd to reset the p2p key + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * fixed compilier error. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * release RX packet to packet pool when in RF test mode + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Add a common buffer, store the IE of a P2P device in this common buffer. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 20 2010 yuche.tsai + * NULL + * When enable WiFi Direct function, check each packet to tell which interface to indicate. + * + * 08 05 2010 yuche.tsai + * NULL + * Add P2P Device Discovery Function. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 yuche.tsai + * NULL + * Add support API for RX public action frame. + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 26 2010 yuche.tsai + * + * Update Device Capability Bitmap & Group Capability Bitmap from 16 bits to 8 bits. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill ucStaRecIdx into SW_RFB_T. + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add TX Done Event handle entry + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync with MT6620 driver for scan result replacement policy + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 04 29 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * fixing the PMKID candicate indicate code. + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * basic implementation for EVENT_BT_OVER_WIFI + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * nicRxProcessEvent packet doesn't access spin-lock directly from now on. + * + * 04 14 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * do not need to release the spin lock due to it is done inside nicGetPendingCmdInfo() + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * 2) add KAPI for handling association info + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve Linux supplicant compliance + * + * 03 31 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl which may cause cmdinfo memory leak + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * rWlanInfo is modified before data is indicated to OS + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * rWlanInfo is modified before data is indicated to OS + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * * the frequency is used for adhoc connection only + * * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * * + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 15 2010 kevin.huang + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Add event for activate STA_RECORD_T + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct fgSetQuery/fgNeedResp check + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c + * * 'cause it involves OS dependent data structure handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Updated API interfaces for qmHandleEventRxAddBa() and qmHandleEventRxDelBa() + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * * 4) nicRxWaitResponse() revised + * * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * * * OID_802_11_RSSI, + * * * * * * OID_802_11_RSSI_TRIGGER, + * * * * * * OID_802_11_STATISTICS, + * * * * * * OID_802_11_DISASSOCIATE, + * * * * * * OID_802_11_POWER_MODE + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * * 2) add 4 counter for recording aggregation statistics + * + * 12 23 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a precheck: if free sw rfb is not enough, do not invoke read transactionu1rwduu`wvpghlqg|fu+rp + * + * 12 22 2009 cp.wu + * [WPD00003809][Bug] Host driver will crash when processing reordered MSDUs + * The root cause is pointer accessing by mistake. After dequeued from reordering-buffer, handling logic should access returned pointer instead of pointer which has been passed in before. +** \main\maintrunk.MT6620WiFiDriver_Prj\58 2009-12-17 13:40:33 GMT mtk02752 +** always update prAdapter->rSDIOCtrl when enhanced response is read by RX +** \main\maintrunk.MT6620WiFiDriver_Prj\57 2009-12-16 18:01:38 GMT mtk02752 +** if interrupt enhanced response is fetched by RX enhanced response, RX needs to invoke interrupt handlers too +** \main\maintrunk.MT6620WiFiDriver_Prj\56 2009-12-16 14:16:52 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\55 2009-12-15 20:03:12 GMT mtk02752 +** ASSERT when RX FreeSwRfb is not enough +** \main\maintrunk.MT6620WiFiDriver_Prj\54 2009-12-15 17:01:29 GMT mtk02752 +** when CFG_SDIO_RX_ENHANCE is enabled, after enhanced response is read, rx procedure should process 1) TX_DONE_INT 2) D2H INT as well +** \main\maintrunk.MT6620WiFiDriver_Prj\53 2009-12-14 20:45:28 GMT mtk02752 +** when CFG_SDIO_RX_ENHANCE is set, TC counter must be updated each time RX enhance response is read +** +** \main\maintrunk.MT6620WiFiDriver_Prj\52 2009-12-14 11:34:16 GMT mtk02752 +** correct a trivial logic issue +** \main\maintrunk.MT6620WiFiDriver_Prj\51 2009-12-14 10:28:25 GMT mtk02752 +** add a protection to avoid out-of-boundary access +** \main\maintrunk.MT6620WiFiDriver_Prj\50 2009-12-10 16:55:18 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\49 2009-12-09 14:06:47 GMT MTK02468 +** Added parsing event packets with EVENT_ID_RX_ADDBA or EVENT_ID_RX_DELBA +** \main\maintrunk.MT6620WiFiDriver_Prj\48 2009-12-08 17:37:51 GMT mtk02752 +** handle EVENT_ID_TEST_STATUS as well +** \main\maintrunk.MT6620WiFiDriver_Prj\47 2009-12-04 17:59:11 GMT mtk02752 +** to pass free-build compilation check +** \main\maintrunk.MT6620WiFiDriver_Prj\46 2009-12-04 12:09:52 GMT mtk02752 +** correct trivial mistake +** \main\maintrunk.MT6620WiFiDriver_Prj\45 2009-12-04 11:53:37 GMT mtk02752 +** all API should be compilable under SD1_SD3_DATAPATH_INTEGRATION == 0 +** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-03 16:19:48 GMT mtk01461 +** Fix the Connected Event +** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-11-30 10:56:18 GMT mtk02752 +** 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-11-30 10:11:27 GMT mtk02752 +** implement replacement for bss scan result +** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-11-27 11:08:05 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-11-26 09:38:59 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-11-26 09:29:40 GMT mtk02752 +** enable packet forwarding path (for AP mode) +** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-11-25 21:37:00 GMT mtk02752 +** sync. with EVENT_SCAN_RESULT_T change, and add an assert for checking event size +** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-25 20:17:41 GMT mtk02752 +** fill HIF_TX_HEADER_T.u2SeqNo +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-25 18:18:57 GMT mtk02752 +** buffer scan result to prGlueInfo->rWlanInfo.arScanResult directly. +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-24 22:42:45 GMT mtk02752 +** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event (not implemented yet) +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-24 20:51:41 GMT mtk02752 +** integrate with SD1's data path API +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-24 19:56:17 GMT mtk02752 +** adopt P_HIF_RX_HEADER_T in new path +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-23 20:31:21 GMT mtk02752 +** payload to send into pfCmdDoneHandler() will not include WIFI_EVENT_T +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-23 17:51:34 GMT mtk02752 +** when event packet corresponding to some pendingOID is received, pendingOID should be cleared +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 14:46:54 GMT mtk02752 +** implement nicRxProcessEventPacket() +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-17 22:40:54 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-16 21:48:22 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION data path handling +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-16 15:41:18 GMT mtk01084 +** modify the length to be read in emu mode +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-13 17:00:12 GMT mtk02752 +** add blank function for event packet +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-13 13:54:24 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 14:41:51 GMT mtk02752 +** fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-11 14:33:46 GMT mtk02752 +** add protection when there is no packet avilable +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 12:33:36 GMT mtk02752 +** add RX1 read path for aggregated/enhanced/normal packet read procedures +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:18 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-04 14:11:08 GMT mtk01084 +** modify lines in RX aggregation +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:23 GMT mtk01084 +** modify RX aggregation handling +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:56:12 GMT mtk01084 +** modify HAL part +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:34 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:20 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-02 13:59:08 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-21 23:39:05 GMT mtk01461 +** Fix the paste error of RX STATUS in OOB of HIF Loopback CTRL +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-20 12:25:32 GMT mtk01461 +** Fix process of Read Done, and add u4MaxEventBufferLen to nicRxWaitResponse() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 21:13:18 GMT mtk01426 +** Fixed compiler error +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:05:29 GMT mtk01426 +** Fixed nicRxSDIOAggReceiveRFBs() ASSERT issue +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:38:43 GMT mtk01461 +** Fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode and refine nicRxSDIOAggeceiveRFBs() for RX Aggregation +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-22 09:12:17 GMT mtk01461 +** Fix nicRxProcessHIFLoopbackPacket(), the size of HIF CTRL LENTH field is 1 byte +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-14 15:51:26 GMT mtk01426 +** Update RX OOB Setting +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-03 14:58:58 GMT mtk01426 +** Fixed logical error +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:58:31 GMT mtk01461 +** Rename the HIF_PKT_TYPE_DATA +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:51:18 GMT mtk01461 +** Fix u4HeaderOffset in nicRxProcessHIFLoopbackPacket() +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:02:58 GMT mtk01426 +** Add CFG_SDIO_RX_ENHANCE and CFG_HIF_LOOPBACK support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:20:59 GMT mtk01426 +** Add nicRxWaitResponse function +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:01 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#ifndef LINUX +#include +#else +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { + #if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ + #else + NULL, /* subtype 0000: Association request */ + #endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ + #if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ + #else + NULL, /* subtype 0010: Reassociation request */ + #endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ + #if CFG_SUPPORT_ADHOC + bssProcessProbeRequest, /* subtype 0100: Probe request */ + #else + NULL, /* subtype 0100: Probe request */ + #endif /* CFG_SUPPORT_ADHOC */ + scanProcessBeaconAndProbeResp, /* subtype 0101: Probe response */ + NULL, /* subtype 0110: reserved */ + NULL, /* subtype 0111: reserved */ + scanProcessBeaconAndProbeResp, /* subtype 1000: Beacon */ + NULL, /* subtype 1001: ATIM */ + saaFsmRunEventRxDisassoc, /* subtype 1010: Disassociation */ + authCheckRxAuthFrameTransSeq, /* subtype 1011: Authentication */ + saaFsmRunEventRxDeauth, /* subtype 1100: Deauthentication */ + nicRxProcessActionFrame, /* subtype 1101: Action */ + NULL, /* subtype 1110: reserved */ + NULL /* subtype 1111: reserved */ +}; +#endif + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucMemHandle; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + UINT_32 i; + + DEBUGFUNC("nicRxInitialize"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + + //4 <0> Clear allocated memory. + kalMemZero((PVOID) prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize); + + //4 <1> Initialize the RFB lists + QUEUE_INITIALIZE(&prRxCtrl->rFreeSwRfbList); + QUEUE_INITIALIZE(&prRxCtrl->rReceivedRfbList); + QUEUE_INITIALIZE(&prRxCtrl->rIndicatedRfbList); + + pucMemHandle = prRxCtrl->pucRxCached; + for (i = CFG_RX_MAX_PKT_NUM; i != 0; i--) { + prSwRfb = (P_SW_RFB_T)pucMemHandle; + + nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + + pucMemHandle += ALIGN_4(sizeof(SW_RFB_T)); + } + + ASSERT(prRxCtrl->rFreeSwRfbList.u4NumElem == CFG_RX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((UINT_32)(pucMemHandle - prRxCtrl->pucRxCached) == prRxCtrl->u4RxCachedSize); + + //4 <2> Clear all RX counters + RX_RESET_ALL_CNTS(prRxCtrl); + +#if CFG_SDIO_RX_AGG + prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + #if !defined(MT5931) + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); + #endif +#else + #if !defined(MT5931) + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); + #endif +#endif + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + + return; +} /* end of nicRxInitialize() */ + + +#if defined(MT5931) +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize HIF RX control registers explicitly +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxPostInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + DEBUGFUNC("nicRxPostInitialize"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + +#if CFG_SDIO_RX_AGG + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); +#else + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); +#endif + +} /* end of nicRxPostInitialize() */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxUninitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + nicRxFlush(prAdapter); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb){ + if (prSwRfb->pvPacket) { + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + } + prSwRfb->pvPacket = NULL; + } + else { + break; + } + }while (TRUE); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb){ + if (prSwRfb->pvPacket) { + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + } + prSwRfb->pvPacket = NULL; + } + else { + break; + } + }while (TRUE); + + return; +} /* end of nicRxUninitialize() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb specify the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxFillRFB ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4PktLen = 0; + UINT_32 u4MacHeaderLen; + UINT_32 u4HeaderOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + u4PktLen= prHifRxHdr->u2PacketLen; + + u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + u4MacHeaderLen = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_LEN) + >> HIF_RX_HDR_HEADER_LEN_OFFSET; + + //DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", + // u4HeaderOffset, u4MacHeaderLen)); + + prSwRfb->u2HeaderLen = (UINT_16)u4MacHeaderLen; + prSwRfb->pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + prSwRfb->u2PacketLen = (UINT_16)(u4PktLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); + + //DBGLOG(RX, TRACE, ("Dump Rx packet, u2PacketLen = %d\n", prSwRfb->u2PacketLen)); + //DBGLOG_MEM8(RX, TRACE, prSwRfb->pvHeader, prSwRfb->u2PacketLen); + +#if 0 + if (prHifRxHdr->ucReorder & HIF_RX_HDR_80211_HEADER_FORMAT){ + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_802_11_FORMAT; + DBGLOG(RX, TRACE, ("HIF_RX_HDR_FLAG_802_11_FORMAT\n")); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_DO_REORDER){ + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_DO_REORDERING; + DBGLOG(RX, TRACE, ("HIF_RX_HDR_FLAG_DO_REORDERING\n")); + + /* Get Seq. No and TID, Wlan Index info */ + if (prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_BAR_FRAME){ + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_BAR_FRAME; + DBGLOG(RX, TRACE, ("HIF_RX_HDR_FLAG_BAR_FRAME\n")); + } + + prSwRfb->u2SSN = prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_SEQ_NO_MASK; + prSwRfb->ucTid = (UINT_8)((prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_TID_MASK) + >> HIF_RX_HDR_TID_OFFSET); + DBGLOG(RX, TRACE, ("u2SSN = %d, ucTid = %d\n", + prSwRfb->u2SSN, prSwRfb->ucTid)); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_WDS){ + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_AMP_WDS; + DBGLOG(RX, TRACE, ("HIF_RX_HDR_FLAG_AMP_WDS\n")); + } +#endif +} + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill checksum status in RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* @param u4TcpUdpIpCksStatus specify the Checksum status +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxFillChksumStatus( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb, + IN UINT_32 u4TcpUdpIpCksStatus +) +{ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prAdapter->u4CSUMFlags != CSUM_NOT_SUPPORTED){ + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv4) { // IPv4 packet + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + if(u4TcpUdpIpCksStatus & RX_CS_STATUS_IP) { //IP packet csum failed + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_SUCCESS; + } + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { //TCP packet + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if(u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { //TCP packet csum failed + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } + else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { //UDP packet + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if(u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { //UDP packet csum failed + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } + else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } + else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv6) {//IPv6 packet + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_SUCCESS; + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { //TCP packet + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if(u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { //TCP packet csum failed + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } + else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { //UDP packet + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if(u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { //UDP packet csum failed + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } + else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } + else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + } + } + +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process packet doesn't need to do buffer reordering +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessPktWithoutReorder ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + BOOL fgIsRetained = FALSE; + UINT_32 u4CurrentRxBufferCount; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + //DBGLOG(RX, TRACE, ("\n")); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C + * => still availble for $C to use + * + */ + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? + TRUE : FALSE); + + //DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); + + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32)prSwRfb->u2PacketLen, + fgIsRetained, + prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, ERROR, ("kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n")); + ASSERT(0); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + else { + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec) { +#if CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && + prAdapter->fgIsP2PRegistered == TRUE) { + GLUE_SET_PKT_FLAG_P2P(prSwRfb->pvPacket); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + GLUE_SET_PKT_FLAG_PAL(prSwRfb->pvPacket); + } +#endif + } + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; + } + + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + /* TODO : error handling of nicRxSetupRFB */ + nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } + else{ + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process forwarding data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessForwardPkt ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_MSDU_INFO_T prMsduInfo, prRetMsduInfoList; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessForwardPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if(prMsduInfo && kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32)prSwRfb->u2PacketLen, + prRxCtrl->rFreeSwRfbList.u4NumElem < CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, + prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + // pack into MSDU_INFO_T + nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET)(prSwRfb->pvPacket)); + // Overwrite the ucNetworkType + prMsduInfo->ucNetworkType = HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr); + + // release RX buffer (to rIndicatedRfbList) + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + + // increase forward frame counter + GLUE_INC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + + // send into TX queue + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfoList = qmEnqueueTxPackets(prAdapter, prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if(prRetMsduInfoList != NULL) { // TX queue refuses queuing the packet + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfoList); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfoList); + } + /* indicate service thread for sending */ + if(prTxCtrl->i4PendingFwdFrameCount > 0) { + kalSetEvent(prAdapter->prGlueInfo); + } + } + else { // no TX resource + nicRxReturnRFB(prAdapter, prSwRfb); + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process broadcast data packet for both host and forwarding +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessGOBroadcastPkt ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_SW_RFB_T prSwRfbDuplicated; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_HIF_RX_HEADER_T prHifRxHdr; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + ASSERT(CFG_NUM_OF_QM_RX_PKT_NUM >= 16); + + if( prRxCtrl->rFreeSwRfbList.u4NumElem + >= (CFG_RX_MAX_PKT_NUM - (CFG_NUM_OF_QM_RX_PKT_NUM - 16 /* Reserved for others */) ) ) { + + /* 1. Duplicate SW_RFB_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if(prSwRfbDuplicated){ + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, + ALIGN_4(prHifRxHdr->u2PacketLen + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = HIF_RX_PKT_TYPE_DATA; + prSwRfbDuplicated->ucStaRecIdx = (UINT_8)(prHifRxHdr->ucStaRecIdx); + nicRxFillRFB(prAdapter, prSwRfbDuplicated); + + /* 2. Modify eDst */ + prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; + + /* 4. Forward */ + nicRxProcessForwardPkt(prAdapter, prSwRfbDuplicated); + } + } + else { + DBGLOG(RX, WARN, ("Stop to forward BMC packet due to less free Sw Rfb %u\n", prRxCtrl->rFreeSwRfbList.u4NumElem)); + } + + /* 3. Indicate to host */ + prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessDataPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prRetSwRfb, prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("nicRxProcessDataPacket"); + //DBGLOG(INIT, TRACE, ("\n")); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + prRxCtrl = &prAdapter->rRxCtrl; + + nicRxFillRFB(prAdapter, prSwRfb); + +#if 1 /* Check 1x Pkt */ + if (prSwRfb->u2PacketLen > 14) { + PUINT_8 pc = (PUINT_8)prSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]); + +#if CFG_SUPPORT_WAPI + if (u2Etype == ETH_P_1X || u2Etype == ETH_WPI_1X) { + DBGLOG(RSN, INFO, ("R1X len=%d\n", prSwRfb->u2PacketLen)); + } +#else + if (u2Etype == ETH_P_1X) { + DBGLOG(RSN, INFO, ("R1X len=%d\n", prSwRfb->u2PacketLen)); + } +#endif + else if (u2Etype == ETH_P_PRE_1X) { + DBGLOG(RSN, INFO, ("Pre R1X len=%d\n", prSwRfb->u2PacketLen)); + } + } +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + { + UINT_32 u4TcpUdpIpCksStatus; + + u4TcpUdpIpCksStatus = *((PUINT_32)((UINT_32)prHifRxHdr + + (UINT_32)(ALIGN_4(prHifRxHdr->u2PacketLen)))); + nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); + + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + prStaRec = cnmGetStaRecByIndex(prAdapter, prHifRxHdr->ucStaRecIdx); + if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && + prAdapter->fgTestMode == FALSE) { +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + + if((prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb)) != NULL) { + do { + // save next first + prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prRetSwRfb); + + switch(prRetSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + nicRxProcessPktWithoutReorder(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_FORWARD: + nicRxProcessForwardPkt(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_HOST_WITH_FORWARD: + nicRxProcessGOBroadcastPkt(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_NULL: + nicRxReturnRFB(prAdapter, prRetSwRfb); + RX_INC_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + break; + + default: + break; + } +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4DequeuedCnt++; +#endif + prRetSwRfb = prNextSwRfb; + } while(prRetSwRfb); + } + } + else { + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF event packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessEventPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + P_WIFI_EVENT_T prEvent; + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("nicRxProcessEventPacket"); + //DBGLOG(INIT, TRACE, ("\n")); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + + // Event Handling + switch(prEvent->ucEID) { + case EVENT_ID_CMD_RESULT: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if(prCmdInfo != NULL) { + P_EVENT_CMD_RESULT prCmdResult; + prCmdResult = (P_EVENT_CMD_RESULT) ((PUINT_8)prEvent + EVENT_HDR_SIZE); + + /* CMD_RESULT should be only in response to Set commands */ + ASSERT(prCmdInfo->fgSetQuery == FALSE || prCmdInfo->fgNeedResp == TRUE); + + if(prCmdResult->ucStatus == 0) { // success + if(prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + } + else if(prCmdInfo->fgIsOid == TRUE) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + } + else if(prCmdResult->ucStatus == 1) { // reject + if(prCmdInfo->fgIsOid == TRUE) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + else if(prCmdResult->ucStatus == 2) { // unknown CMD + if(prCmdInfo->fgIsOid == TRUE) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_NOT_SUPPORTED); + } + + // return prCmdInfo + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + P_EVENT_CONNECTION_STATUS prConnectionStatus; + prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { // disconnected + if(kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, + 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + } + else if(prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { // connected + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + // fill information for association result + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen + = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, + prConnectionStatus->ucSsidLen); + + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, + MAC_ADDR_LEN); + + prAdapter->rWlanInfo.rCurrBssId.u4Privacy + = prConnectionStatus->ucEncryptStatus; // @FIXME + prAdapter->rWlanInfo.rCurrBssId.rRssi + = 0; //@FIXME + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse + = PARAM_NETWORK_TYPE_AUTOMODE; //@FIXME + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType + = prConnectionStatus->ucNetworkType; + + switch(prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + } + // always indicate to OS according to MSDN (re-association/roaming) + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, + NULL, + 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement will be established */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement has been deleted */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_LINK_QUALITY: +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + if (prEvent->u2PacketLen == EVENT_HDR_SIZE + sizeof(EVENT_LINK_QUALITY_EX)) { + P_EVENT_LINK_QUALITY_EX prLqEx = (P_EVENT_LINK_QUALITY_EX)(prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) { + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY)prLqEx); + } + if (prLqEx->ucIsLQ1Rdy) { + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_P2P_INDEX, (P_EVENT_LINK_QUALITY)prLqEx); + } + } + else { + /* For old FW, P2P may invoke link quality query, and make driver flag becone TRUE. */ + DBGLOG(P2P, WARN, ("Old FW version, not support P2P RSSI query.\n")); + + /* Must not use NETWORK_TYPE_P2P_INDEX, cause the structure is mismatch. */ + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY)(prEvent->aucBuffer)); + } +#else + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY)(prEvent->aucBuffer)); +#endif + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if(prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + } + else if(prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + // return prCmdInfo + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + #ifndef LINUX + if(prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_GREATER && + prAdapter->rWlanInfo.rRssiTriggerValue >= (PARAM_RSSI)(prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &(prAdapter->rWlanInfo.rRssiTriggerValue), sizeof(PARAM_RSSI)); + } + else if(prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_LESS && + prAdapter->rWlanInfo.rRssiTriggerValue <= (PARAM_RSSI)(prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &(prAdapter->rWlanInfo.rRssiTriggerValue), sizeof(PARAM_RSSI)); + } + #endif + + break; + + case EVENT_ID_MIC_ERR_INFO: + { + P_EVENT_MIC_ERR_INFO prMicError; + //P_PARAM_AUTH_EVENT_T prAuthEvent; + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, EVENT, ("EVENT_ID_MIC_ERR_INFO\n")); + + prMicError = (P_EVENT_MIC_ERR_INFO)(prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_AIS_INDEX, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) { + rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN)prMicError->u4Flags); + } + else { + DBGLOG(RSN, INFO, ("No STA rec!!\n")); + } +#if 0 + prAuthEvent = (P_PARAM_AUTH_EVENT_T)prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID)prAuthEvent->arRequest[0].arBssid, + (PVOID)prAdapter->rWlanInfo.rCurrBssId.arMacAddress, /* whsu:Todo? */ + PARAM_MAC_ADDR_LEN); + + if (prMicError->u4Flags != 0) { + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + } + else { + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); +#endif + } + break; + + case EVENT_ID_ASSOC_INFO: + { + P_EVENT_ASSOC_INFO prAssocInfo; + prAssocInfo = (P_EVENT_ASSOC_INFO)(prEvent->aucBuffer); + + kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); + } + break; + + case EVENT_ID_802_11_PMKID: + { + P_PARAM_AUTH_EVENT_T prAuthEvent; + PUINT_8 cp; + UINT_32 u4LenOfUsedBuffer; + + prAuthEvent = (P_PARAM_AUTH_EVENT_T)prAdapter->aucIndicationEventBuffer; + + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + + u4LenOfUsedBuffer = (UINT_32)(prEvent->u2PacketLen - 8); + + prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; + + cp = (PUINT_8)&prAuthEvent->arRequest[0]; + + /* Status type: PMKID Candidatelist Event */ + kalMemCopy(cp, (P_EVENT_PMKID_CANDIDATE_LIST_T)(prEvent->aucBuffer), prEvent->u2PacketLen - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); + } + break; + +#if 0 + case EVENT_ID_ACTIVATE_STA_REC_T: + { + P_EVENT_ACTIVATE_STA_REC_T prActivateStaRec; + prActivateStaRec = (P_EVENT_ACTIVATE_STA_REC_T)(prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_ACTIVATE_STA_REC_T Index:%d, MAC:["MACSTR"]\n", + prActivateStaRec->ucStaRecIdx, + MAC2STR(prActivateStaRec->aucMacAddr)); + + qmActivateStaRec(prAdapter, + (UINT_32)prActivateStaRec->ucStaRecIdx, + ((prActivateStaRec->fgIsQoS) ? TRUE: FALSE), + prActivateStaRec->ucNetworkTypeIndex, + ((prActivateStaRec->fgIsAP) ? TRUE: FALSE), + prActivateStaRec->aucMacAddr); + + } + break; + + case EVENT_ID_DEACTIVATE_STA_REC_T: + { + P_EVENT_DEACTIVATE_STA_REC_T prDeactivateStaRec; + prDeactivateStaRec = (P_EVENT_DEACTIVATE_STA_REC_T)(prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_DEACTIVATE_STA_REC_T Index:%d, MAC:["MACSTR"]\n", + prDeactivateStaRec->ucStaRecIdx); + + qmDeactivateStaRec(prAdapter, + prDeactivateStaRec->ucStaRecIdx); + } + break; +#endif + + case EVENT_ID_SCAN_DONE: + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE)(prEvent->aucBuffer)); + break; + + case EVENT_ID_TX_DONE: + { + P_EVENT_TX_DONE_T prTxDone; + prTxDone = (P_EVENT_TX_DONE_T)(prEvent->aucBuffer); + + DBGLOG(INIT, TRACE,("EVENT_ID_TX_DONE PacketSeq:%u ucStatus: %u SN: %u\n", + prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->u2SequenceNumber)); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(INIT, TRACE, ("EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", + prTxDone->au4Reserved1, prTxDone->au4Reserved2)); + + wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, + prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); +#endif + + if(prMsduInfo) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, (ENUM_TX_RESULT_CODE_T)(prTxDone->ucStatus)); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } + break; + + case EVENT_ID_SLEEPY_NOTIFY: + { + P_EVENT_SLEEPY_NOTIFY prEventSleepyNotify; + prEventSleepyNotify = (P_EVENT_SLEEPY_NOTIFY)(prEvent->aucBuffer); + + //DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); + + prAdapter->fgWiFiInSleepyState = (BOOLEAN)(prEventSleepyNotify->ucSleepyState); + } + break; + case EVENT_ID_BT_OVER_WIFI: +#if CFG_ENABLE_BT_OVER_WIFI + { + UINT_8 aucTmp[sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)]; + P_EVENT_BT_OVER_WIFI prEventBtOverWifi; + P_AMPC_EVENT prBowEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + + prEventBtOverWifi = (P_EVENT_BT_OVER_WIFI)(prEvent->aucBuffer); + + // construct event header + prBowEvent = (P_AMPC_EVENT)aucTmp; + + if(prEventBtOverWifi->ucLinkStatus == 0) { + // Connection + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + // fill event body + prBowLinkConnected = (P_BOW_LINK_CONNECTED)(prBowEvent->aucPayload); + prBowLinkConnected->rChannel.ucChannelNum = prEventBtOverWifi->ucSelectedChannel; + kalMemZero(prBowLinkConnected->aucPeerAddress, MAC_ADDR_LEN); //@FIXME + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } + else { + // Disconnection + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + // fill event body + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED)(prBowEvent->aucPayload); + prBowLinkDisconnected->ucReason = 0; //@FIXME + kalMemZero(prBowLinkDisconnected->aucPeerAddress, MAC_ADDR_LEN); //@FIXME + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } + } + break; +#endif + case EVENT_ID_STATISTICS: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, sizeof(EVENT_STATISTICS)); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if(prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + } + else if(prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + // return prCmdInfo + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + + case EVENT_ID_CH_PRIVILEGE: + cnmChMngrHandleChEvent(prAdapter, prEvent); + break; + + case EVENT_ID_BSS_ABSENCE_PRESENCE: + qmHandleEventBssAbsencePresence(prAdapter, prEvent); + break; + + case EVENT_ID_STA_CHANGE_PS_MODE: + qmHandleEventStaChangePsMode(prAdapter, prEvent); + break; +#if CFG_ENABLE_WIFI_DIRECT + case EVENT_ID_STA_UPDATE_FREE_QUOTA: + qmHandleEventStaUpdateFreeQuota(prAdapter, prEvent); + break; +#endif + case EVENT_ID_BSS_BEACON_TIMEOUT: + DBGLOG(INIT, INFO,("EVENT_ID_BSS_BEACON_TIMEOUT\n")); + + if (prAdapter->fgDisBcnLostDetection == FALSE) { + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T)(prEvent->aucBuffer); + + if(prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + aisBssBeaconTimeout(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if((prAdapter->fgIsP2PRegistered) && + (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) { + + p2pFsmRunEventBeaconTimeout(prAdapter); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if(prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + } +#endif + else { + DBGLOG(RX, ERROR, ("EVENT_ID_BSS_BEACON_TIMEOUT: (ucNetTypeIdx = %d)\n", + prEventBssBeaconTimeout->ucNetTypeIndex)); + } + } + + break; + case EVENT_ID_UPDATE_NOA_PARAMS: +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered){ + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam; + prEventUpdateNoaParam = (P_EVENT_UPDATE_NOA_PARAMS_T)(prEvent->aucBuffer); + + if (prEventUpdateNoaParam->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + p2pProcessEvent_UpdateNOAParam(prAdapter, + prEventUpdateNoaParam->ucNetTypeIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T)NULL; + + prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T)(prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) { + break; + } + + DBGLOG(INIT, INFO,("EVENT_ID_STA_AGING_TIMEOUT %u " MACSTR "\n", + prEventStaAgingTimeout->ucStaRecIdx, MAC2STR(prStaRec->aucMacAddr))); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prStaRec, TRUE, REASON_CODE_DISASSOC_INACTIVITY); + } + + + } /* gDisStaAgingTimeoutDetection */ + + } +#endif + break; + + case EVENT_ID_AP_OBSS_STATUS: +#if CFG_ENABLE_WIFI_DIRECT + if(prAdapter->fgIsP2PRegistered){ + rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); + } +#endif + break; + + case EVENT_ID_ROAMING_STATUS: +#if CFG_SUPPORT_ROAMING + { + P_ROAMING_PARAM_T prParam; + + prParam = (P_ROAMING_PARAM_T)(prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prParam); + } +#endif /* CFG_SUPPORT_ROAMING */ + break; + case EVENT_ID_SEND_DEAUTH: +#if DBG + { + P_WLAN_MAC_HEADER_T prWlanMacHeader; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T)&prEvent->aucBuffer[0]; + DBGLOG(RX, INFO, ("nicRx: aucAddr1: "MACSTR"\n", MAC2STR(prWlanMacHeader->aucAddr1))); + DBGLOG(RX, INFO, ("nicRx: aucAddr2: "MACSTR"\n", MAC2STR(prWlanMacHeader->aucAddr2))); + } +#endif + /* receive packets without StaRec */ + prSwRfb->pvHeader = (P_WLAN_MAC_HEADER_T)&prEvent->aucBuffer[0]; + if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER)NULL)) { + DBGLOG(RX, INFO, ("Send Deauth Error\n")); + } + break; + +#if CFG_SUPPORT_RDD_TEST_MODE + case EVENT_ID_UPDATE_RDD_STATUS: + { + P_EVENT_RDD_STATUS_T prEventRddStatus; + + prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; + } + + break; +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case EVENT_ID_UPDATE_BWCS_STATUS: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + printk(KERN_INFO DRV_NAME "BCM BWCS Event: %02x%02x%02x%02x\n", prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); + + printk(KERN_INFO DRV_NAME "BCM BWCS Event: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[3] = %02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_BWCS_UPDATE, + (PVOID) prEventBwcsStatus, + sizeof(PTA_IPC_T)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + printk(KERN_INFO DRV_NAME "BCM FW status: %02x%02x%02x%02x\n", prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); + + printk(KERN_INFO DRV_NAME "BCM FW status: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[3] = %02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif + } + + break; +#endif + + case EVENT_ID_ACCESS_REG: + case EVENT_ID_NIC_CAPABILITY: + case EVENT_ID_BASIC_CONFIG: + case EVENT_ID_MAC_MCAST_ADDR: + case EVENT_ID_ACCESS_EEPROM: + case EVENT_ID_TEST_STATUS: + default: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if(prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + } + else if(prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + // return prCmdInfo + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicRxProcessMgmtPacket is used to dispatch management frames +* to corresponding modules +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessMgmtPacket ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + UINT_8 ucSubtype; +#if CFG_SUPPORT_802_11W + BOOL fgMfgDrop = FALSE; +#endif + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + + ucSubtype = (*(PUINT_8)(prSwRfb->pvHeader) & MASK_FC_SUBTYPE )>> OFFSET_OF_FC_SUBTYPE; + +#if CFG_RX_PKTS_DUMP + { + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2TxFrameCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + u2TxFrameCtrl = (*(PUINT_8)(prSwRfb->pvHeader) & MASK_FRAME_TYPE); + if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_MANAGEMENT)) { + if (u2TxFrameCtrl == MAC_FRAME_BEACON || + u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { + + DBGLOG(SW4, INFO, ("QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), + prHifRxHdr->ucStaRecIdx, + prSwRfb->ucWlanIdx, + HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ + prSwRfb->ucPacketType, + ucSubtype, + HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr))); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prSwRfb->pvHeader, prSwRfb->u2PacketLen); + } + } + } +#endif + + if(prAdapter->fgTestMode == FALSE) { +#if CFG_MGMT_FRAME_HANDLING +#if CFG_SUPPORT_802_11W + fgMfgDrop = rsnCheckRxMgmt(prAdapter, prSwRfb, ucSubtype); + if (fgMfgDrop) { + #if DBG + LOG_FUNC("QM RX MGT: Drop Unprotected Mgmt frame!!!\n"); + #endif + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } + else +#endif + if(apfnProcessRxMgtFrame[ucSubtype]) { + switch(apfnProcessRxMgtFrame[ucSubtype](prAdapter, prSwRfb)){ + case WLAN_STATUS_PENDING: + return; + case WLAN_STATUS_SUCCESS: + case WLAN_STATUS_FAILURE: + break; + + default: + DBGLOG(RX, WARN, ("Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype)); + break; + } + } +#endif + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxProcessRFBs ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb){ + switch(prSwRfb->ucPacketType){ + case HIF_RX_PKT_TYPE_DATA: + nicRxProcessDataPacket(prAdapter, prSwRfb); + break; + + case HIF_RX_PKT_TYPE_EVENT: + nicRxProcessEventPacket(prAdapter, prSwRfb); + break; + + case HIF_RX_PKT_TYPE_TX_LOOPBACK: + DBGLOG(RX, ERROR, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); + break; + + case HIF_RX_PKT_TYPE_MANAGEMENT: + nicRxProcessMgmtPacket(prAdapter, prSwRfb); + break; + + default: + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); + break; + } + } + else { + break; + } + }while(TRUE); + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); + + //DBGLOG(RX, INFO, ("%d packets indicated, Retained cnt = %d\n", + // prRxCtrl->ucNumIndPacket, prRxCtrl->ucNumRetainedPacket)); + #if CFG_NATIVE_802_11 + kalRxIndicatePkts(prAdapter->prGlueInfo, (UINT_32)prRxCtrl->ucNumIndPacket, (UINT_32)prRxCtrl->ucNumRetainedPacket); + #else + kalRxIndicatePkts(prAdapter->prGlueInfo, prRxCtrl->apvIndPacket, (UINT_32)prRxCtrl->ucNumIndPacket); + #endif + } + +} /* end of nicRxProcessRFBs() */ + + +#if !CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the rx data from data port and setup RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @retval WLAN_STATUS_SUCCESS: SUCCESS +* @retval WLAN_STATUS_FAILURE: FAILURE +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxReadBuffer ( + IN P_ADAPTER_T prAdapter, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0, u4ReadBytes; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOL fgResult = TRUE; + UINT_32 u4RegValue; + UINT_32 rxNum; + + DEBUGFUNC("nicRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(pucBuf); + DBGLOG(RX, TRACE, ("pucBuf= 0x%x, prHifRxHdr= 0x%x\n", pucBuf, prHifRxHdr)); + + do { + /* Read the RFB DW length and packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4RegValue); + if (!fgResult) { + DBGLOG(RX, ERROR, ("Read RX Packet Lentgh Error\n")); + return WLAN_STATUS_FAILURE; + } + + //20091021 move the line to get the HIF RX header (for RX0/1) + if(u4RegValue == 0) { + DBGLOG(RX, ERROR, ("No RX packet\n")); + return WLAN_STATUS_FAILURE; + } + + u4PktLen = u4RegValue & BITS(0, 15); + if(u4PktLen != 0) { + rxNum = 0; + } + else { + rxNum = 1; + u4PktLen = (u4RegValue & BITS(16, 31)) >> 16; + } + + DBGLOG(RX, TRACE, ("RX%d: u4PktLen = %d\n", rxNum, u4PktLen)); + + //4 <4> Read Entire RFB and packet, include HW appended DW (Checksum Status) + u4ReadBytes = ALIGN_4(u4PktLen) + 4; + HAL_READ_RX_PORT(prAdapter, rxNum, u4ReadBytes, pucBuf, CFG_RX_MAX_PKT_SIZE); + + //20091021 move the line to get the HIF RX header + //u4PktLen = (UINT_32)prHifRxHdr->u2PacketLen; + if (u4PktLen != (UINT_32)prHifRxHdr->u2PacketLen) { + DBGLOG(RX, ERROR, ("Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, prHifRxHdr->u2PacketLen)); + #if DBG + dumpMemory8((PUINT_8)prHifRxHdr, (prHifRxHdr->u2PacketLen > 4096) ? 4096 : prHifRxHdr->u2PacketLen); + #endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (UINT_8)(prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); + + prSwRfb->ucStaRecIdx = (UINT_8)(prHifRxHdr->ucStaRecIdx); + + /* fgResult will be updated in MACRO */ + if (!fgResult) { + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RX, TRACE, ("Dump RX buffer, length = 0x%x\n", u4ReadBytes)); + DBGLOG_MEM8(RX, TRACE, pucBuf, u4ReadBytes); + }while(FALSE); + + return u4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4HwAppendDW; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, ("No More RFB\n")); + break; + } + + // need to consider + if (nicRxReadBuffer(prAdapter, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, ("halRxFillRFB failed\n")); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + prHifRxHdr = prSwRfb->prHifRxHdr; + u4HwAppendDW = *((PUINT_32)((UINT_32)prHifRxHdr + + (UINT_32)(ALIGN_4(prHifRxHdr->u2PacketLen)))); + DBGLOG(RX, TRACE, ("u4HwAppendDW = 0x%x\n", u4HwAppendDW)); + DBGLOG(RX, TRACE, ("u2PacketLen = 0x%x\n", prHifRxHdr->u2PacketLen)); + } +// while (RX_STATUS_TEST_MORE_FLAG(u4HwAppendDW)); + while (FALSE); + + return; + +} /* end of nicReceiveRFBs() */ + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4DataPort Specify which port to read +* @param u2RxLength Specify to the the rx packet length in Byte. +* @param prSwRfb the RFB to receive rx data. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRxEnhanceReadBuffer ( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, + IN UINT_16 u2RxLength, + IN OUT P_SW_RFB_T prSwRfb + ) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + BOOL fgResult = TRUE; + + DEBUGFUNC("nicRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + //DBGLOG(RX, TRACE, ("u2RxLength = %d\n", u2RxLength)); + + do { + //4 <1> Read RFB frame from MCR_WRDR0, include HW appended DW + HAL_READ_RX_PORT(prAdapter, + u4DataPort, + ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN), + pucBuf, + CFG_RX_MAX_PKT_SIZE); + + if (!fgResult) { + DBGLOG(RX, ERROR, ("Read RX Packet Lentgh Error\n")); + break; + } + + u4PktLen = (UINT_32)(prHifRxHdr->u2PacketLen); + //DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); + + prSwRfb->ucPacketType = (UINT_8)(prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + //DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); + + prSwRfb->ucStaRecIdx = (UINT_8)(prHifRxHdr->ucStaRecIdx); + + //4 <2> if the RFB dw size or packet size is zero + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, ("Packet Length = %d\n", u4PktLen)); + ASSERT(0); + break; + } + + //4 <3> if the packet is too large or too small + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, ("Read RX Packet Lentgh Error (%d)\n", u4PktLen)); + ASSERT(0); + break; + } + + u4Status = WLAN_STATUS_SUCCESS; + } + while (FALSE); + + DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); + return u4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxSDIOReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SDIO_CTRL_T prSDIOCtrl; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + UINT_32 i, rxNum; + UINT_16 u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0 ; rxNum < 2 ; rxNum++) { + u2RxPktNum = (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if(u2RxPktNum == 0) { + continue; + } + + for (i = 0; i < u2RxPktNum; i++) { + if(rxNum == 0) { + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } + else if(rxNum == 1) { + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) { + break; + } + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, ("No More RFB\n")); + break; + } + ASSERT(prSwRfb); + + if (nicRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, ("nicRxEnhanceRxReadBuffer failed\n")); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + + //prSDIOCtrl->au4RxLength[i] = 0; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + + return; +}/* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxSDIOAggReceiveRFBs ( + IN P_ADAPTER_T prAdapter + ) +{ + P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; + P_RX_CTRL_T prRxCtrl; + P_SDIO_CTRL_T prSDIOCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T)NULL; + UINT_32 u4RxLength; + UINT_32 i, rxNum; + UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; + UINT_32 u4RxAvailAggLen, u4CurrAvailFreeRfbCnt; + PUINT_8 pucSrcAddr; + P_HIF_RX_HEADER_T prHifRxHdr; + BOOL fgResult = TRUE; + BOOLEAN fgIsRxEnhanceMode; + UINT_16 u2RxPktNum; +#if CFG_SDIO_RX_ENHANCE + UINT_32 u4MaxLoopCount = CFG_MAX_RX_ENHANCE_LOOP_COUNT; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + prEnhDataStr = prAdapter->prSDIOCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + prSDIOCtrl = prAdapter->prSDIOCtrl; + +#if CFG_SDIO_RX_ENHANCE + fgIsRxEnhanceMode = TRUE; +#else + fgIsRxEnhanceMode = FALSE; +#endif + + do { +#if CFG_SDIO_RX_ENHANCE + /* to limit maximum loop for RX */ + u4MaxLoopCount--; + if (u4MaxLoopCount == 0) { + break; + } +#endif + + if(prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) { + break; + } + + for(rxNum = 0 ; rxNum < 2 ; rxNum++) { + u2RxPktNum = (rxNum == 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + //DBGLOG(RX, TRACE, ("RxPktNum %d in rxPort %d\n", u2RxPktNum, rxNum)); + // if this assertion happened, it is most likely a F/W bug + ASSERT(u2RxPktNum <= 16); + + if (u2RxPktNum > 16) + continue; + + if(u2RxPktNum == 0) + continue; + + #if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; + #endif + + u4CurrAvailFreeRfbCnt = prRxCtrl->rFreeSwRfbList.u4NumElem; + + // if SwRfb is not enough, abort reading this time + if(u4CurrAvailFreeRfbCnt < u2RxPktNum) { + #if CFG_HIF_RX_STARVATION_WARNING + DbgPrint("FreeRfb is not enough: %d available, need %d\n", u4CurrAvailFreeRfbCnt, u2RxPktNum); + DbgPrint("Queued Count: %d / Dequeud Count: %d\n", prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt); + #endif + continue; + } + +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen = CFG_RX_COALESCING_BUFFER_SIZE - (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + 4/* extra HW padding */); +#else + u4RxAvailAggLen = CFG_RX_COALESCING_BUFFER_SIZE; +#endif + u4RxAggCount = 0; + + for (i = 0; i < u2RxPktNum ; i++) { + u4RxLength = (rxNum == 0 ? + (UINT_32)prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + (UINT_32)prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (!u4RxLength) { + ASSERT(0); + break; + } + + if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { + if (u4RxAggCount < u4CurrAvailFreeRfbCnt) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + } + else { + // no FreeSwRfb for rx packet + ASSERT(0); + break; + } + } + else { + // CFG_RX_COALESCING_BUFFER_SIZE is not large enough + ASSERT(0); + break; + } + } + + u4RxAggLength = (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + //DBGLOG(RX, INFO, ("u4RxAggCount = %d, u4RxAggLength = %d\n", + // u4RxAggCount, u4RxAggLength)); + + HAL_READ_RX_PORT(prAdapter, + rxNum, + u4RxAggLength, + prRxCtrl->pucRxCoalescingBufPtr, + CFG_RX_COALESCING_BUFFER_SIZE); + if (!fgResult) { + DBGLOG(RX, ERROR, ("Read RX Agg Packet Error\n")); + continue; + } + + pucSrcAddr = prRxCtrl->pucRxCoalescingBufPtr; + for (i = 0; i < u4RxAggCount; i++) { + UINT_16 u2PktLength; + + u2PktLength = (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + ASSERT(prSwRfb); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + prSwRfb->ucPacketType = (UINT_8)(prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + //DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); + + prSwRfb->ucStaRecIdx = (UINT_8)(prHifRxHdr->ucStaRecIdx); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + //prEnhDataStr->au4RxLength[i] = 0; + } + +#if CFG_SDIO_RX_ENHANCE + kalMemCopy(prAdapter->prSDIOCtrl, (pucSrcAddr + 4), sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + /* do the same thing what nicSDIOReadIntStatus() does */ + if((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + /* dispatch to interrupt handler with RX bits masked */ + nicProcessIST_impl(prAdapter, prSDIOCtrl->u4WHISR & (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT))); +#endif + } + +#if !CFG_SDIO_RX_ENHANCE + prEnhDataStr->rRxInfo.u.u2NumValidRx0Len = 0; + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len = 0; +#endif + } + while ((prEnhDataStr->rRxInfo.u.u2NumValidRx0Len + || prEnhDataStr->rRxInfo.u.u2NumValidRx1Len) + && fgIsRxEnhanceMode); + + return; +} +#endif /* CFG_SDIO_RX_AGG */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Setup a RFB and allocate the os packet to the RFB +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_RESOURCES +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxSetupRFB ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + PVOID pvPacket; + PUINT_8 pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(SW_RFB_T)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, + &pucRecvBuff); + if (pvPacket == NULL) { + return WLAN_STATUS_RESOURCES; + } + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff= (PVOID)pucRecvBuff; + } + else { + kalMemZero(((PUINT_8)prSwRfb + OFFSET_OF(SW_RFB_T, prHifRxHdr)), + (sizeof(SW_RFB_T)-OFFSET_OF(SW_RFB_T, prHifRxHdr))); + } + + prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T)(prSwRfb->pucRecvBuff); + + return WLAN_STATUS_SUCCESS; + +} /* end of nicRxSetupRFB() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to put a RFB back onto the "RFB with Buffer" list +* or "RFB without buffer" list according to pvPacket. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxReturnRFB ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_RX_CTRL_T prRxCtrl; + P_QUE_ENTRY_T prQueEntry; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRxCtrl = &prAdapter->rRxCtrl; + prQueEntry = &prSwRfb->rQueEntry; + + ASSERT(prQueEntry); + + /* The processing on this RFB is done, so put it back on the tail of + our list */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb->pvPacket) { + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } + else { + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + return; +} /* end of nicRxReturnRFB() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicProcessRxInterrupt ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + #if CFG_SDIO_RX_AGG + nicRxSDIOAggReceiveRFBs(prAdapter); + #else + nicRxSDIOReceiveRFBs(prAdapter); + #endif +#else + nicRxReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicRxProcessRFBs(prAdapter); + + return; + +} /* end of nicProcessRxInterrupt() */ + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief Used to update IP/TCP/UDP checksum statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param aeCSUM The array of checksum result. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxUpdateCSUMStatistics ( + IN P_ADAPTER_T prAdapter, + IN const ENUM_CSUM_RESULT_T aeCSUM[] + ) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + ASSERT(aeCSUM); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS) || + (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)) { + + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } + else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || + (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } + else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && + (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } + else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } + else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && + (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } + else { + ASSERT(0); + } + + return; +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current status of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxQueryStatus ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + OUT PUINT_32 pu4Count + ) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + //if (pucBuffer) {} /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + + SPRINTF(pucCurrBuf, ("\n\nRX CTRL STATUS:")); + SPRINTF(pucCurrBuf, ("\n===============")); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/i BUF LIST :%9ld", prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/o BUF LIST :%9ld", prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nRECEIVED RFB LIST :%9ld", prRxCtrl->rReceivedRfbList.u4NumElem)); + + SPRINTF(pucCurrBuf, ("\n\n")); + + //*pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); + + return; +} /* end of nicRxQueryStatus() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear RX related counters +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return - (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxClearStatistics ( + IN P_ADAPTER_T prAdapter + ) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxQueryStatistics ( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, + OUT PUINT_32 pu4Count + ) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + //if (pucBuffer) {} /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + +#define SPRINTF_RX_COUNTER(eCounter) \ + SPRINTF(pucCurrBuf, ("%-30s : %ld\n", #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter])) + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + //*pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); + + nicRxClearStatistics(prAdapter); + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the Response data from data port +* +* @param prAdapter pointer to the Adapter handler +* @param pucRspBuffer pointer to the Response buffer +* +* @retval WLAN_STATUS_SUCCESS: Response packet has been read +* @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxWaitResponse ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, + OUT PUINT_8 pucRspBuffer, + IN UINT_32 u4MaxRespBufferLen, + OUT PUINT_32 pu4Length + ) +{ + UINT_32 u4Value = 0, u4PktLen = 0, i = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOL fgResult = TRUE; + UINT_32 u4Time, u4Current; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + u4Time = (UINT_32)kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if (!fgResult) { + DBGLOG(RX, ERROR, ("Read Response Packet Error\n")); + return WLAN_STATUS_FAILURE; + } + + if(ucPortIdx == 0) { + u4PktLen = u4Value & 0xFFFF; + } + else { + u4PktLen = (u4Value >> 16) & 0xFFFF; + } + + DBGLOG(RX, TRACE, ("i = %d, u4PktLen = %d\n", i, u4PktLen)); + + if (u4PktLen == 0) { + /* timeout exceeding check */ + u4Current = (UINT_32)kalGetTimeTick(); + + if((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { + return WLAN_STATUS_FAILURE; + } + else if(u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + + i++; + } + else if (u4PktLen > u4MaxRespBufferLen) { + DBGLOG(RX, WARN, ("Not enough Event Buffer: required length = 0x%x, available buffer length = %d\n", + u4PktLen, u4MaxRespBufferLen)); + + return WLAN_STATUS_FAILURE; + } + else { + HAL_PORT_RD(prAdapter, + ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, + u4PktLen, + pucRspBuffer, + u4MaxRespBufferLen); + + /* fgResult will be updated in MACRO */ + if (!fgResult) { + DBGLOG(RX, ERROR, ("Read Response Packet Error\n")); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RX, TRACE, ("Dump Response buffer, length = 0x%x\n", + u4PktLen)); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, u4PktLen); + + *pu4Length = u4PktLen; + break; + } + } while(TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to enable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxEnablePromiscuousMode ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return; +} /* end of nicRxEnablePromiscuousMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to disable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxDisablePromiscuousMode ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return; +} /* end of nicRxDisablePromiscuousMode() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in reordering module +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxFlush ( + IN P_ADAPTER_T prAdapter + ) +{ + P_SW_RFB_T prSwRfb; + + ASSERT(prAdapter); + + if((prSwRfb = qmFlushRxQueues(prAdapter)) != NULL) { + do { + P_SW_RFB_T prNextSwRfb; + + // save next first + prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prSwRfb); + + // free + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while(prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxProcessActionFrame ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_ACTION_FRAME prActFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) { + return WLAN_STATUS_INVALID_PACKET; + } + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + + switch (prActFrame->ucCategory) { + case CATEGORY_PUBLIC_ACTION: + + #if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + rlmProcessPublicAction(prAdapter, prSwRfb); + + p2pFuncValidateRxActionFrame( + prAdapter, prSwRfb); + + } + #endif + break; + + case CATEGORY_HT_ACTION: + #if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + rlmProcessHtAction(prAdapter, prSwRfb); + } + #endif + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: + #if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); + } + #endif + break; +#if CFG_SUPPORT_802_11W + case CATEGORY_SA_QUERT_ACTION: + { + P_HIF_RX_HEADER_T prHifRxHdr; + + prHifRxHdr = prSwRfb->prHifRxHdr; + + if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */ + ) { + if (!(prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC)) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } + else { + DBGLOG(RSN, TRACE, ("Un-Protected SA Query, do nothing\n")); + } + } + } + break; +#endif +#if CFG_SUPPORT_802_11V + case CATEGORY_WNM_ACTION: + { + wnmWNMAction(prAdapter, prSwRfb); + } + break; +#endif + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c new file mode 100755 index 000000000000..641f58565cd1 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c @@ -0,0 +1,1977 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#1 $ +*/ + +/*! \file nic_tx.c + \brief Functions that provide TX operation in NIC Layer. + + This file provides TX functions which are responsible for both Hardware and + Software Resource Management and keep their Synchronization. +*/ + + + +/* +** $Log: nic_tx.c $ + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add log counter for tx + * + * 11 09 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for beacon timeout and sta aging timeout. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 05 17 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection + * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path + * remove unused variables. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 02 16 2011 cp.wu + * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking availble count and modify behavior + * 1. add new API: nicTxGetFreeCmdCount() + * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information + * fill mac header length information for 802.1x frames. + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 27 2010 wh.su + * NULL + * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error + * + * 09 24 2010 wh.su + * NULL + * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 05 2010 yuche.tsai + * NULL + * . + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add checking for TX descriptor poll. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change zero-padding for TX port access to HAL. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill extra information for revised HIF_TX_HEADER. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change to enqueue TX frame infinitely. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add TX_PACKET_MGMT to indicate the frame is coming from management modules + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Tag the packet for QoS on Tx path + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * * * + * +* 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * avoid refering to NDIS-specific data structure directly from non-glue layer. + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add Ethernet destination address information in packet info for TX + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * * * 4) nicRxWaitResponse() revised + * * * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * * * 4. correct some HAL implementation + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 01 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752 +** remove unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752 +** correct assertion criterion +** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752 +** correct trivial mistake +** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752 +** + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data +** + add more assertion for packet size check +** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752 +** nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort +** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752 +** add 2 assertion for size check +** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752 +** use TC4 instead of TC5 for command packet +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752 +** fill prMsduInfo->ucUserPriority +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752 +** fill u2SeqNo +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752 +** integration with SD1's data path API +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752 +** nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752 +** add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, WIFI_CMD_T will be created inside oid handler +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752 +** use TxAccquireResource instead of accessing TCQ directly. +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752 +** add nicTxMsduInfoList () implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752 +** add nicTxAdjustTcq() implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752 +** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION data path handling +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084 +** modify TX hdr format, fix tx retransmission issue +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084 +** modify TX SW data structure +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084 +** modify HAL part +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461 +** Assign SeqNum to CMD Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461 +** Fix Query Command need resp issue +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461 +** Move OS dependent code to kalQueryTxOOBData() +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461 +** Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461 +** Update nicTxCmd() for moving wait RESP function call to wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461 +** Move the CMD_INFO_T related function to cmd_buf.c +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426 +** Update OOB query for TX packet +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426 +** Support PKGUIO +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461 +** Add virtual OOB for HIF LOOPBACK SW PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461 +** Add function for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461 +** Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test. +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461 +** Add code for TX Data & Cmd Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461 +** Fix LINT warning +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial all variables in regard to SW TX Queues and +* all free lists of MSDU_INFO_T and SW_TFCB_T. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxInitialize ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucMemHandle; + P_MSDU_INFO_T prMsduInfo; + UINT_32 i; + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxInitialize"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + //4 <1> Initialization of Traffic Class Queue Parameters + nicTxResetResource(prAdapter); + +#if CFG_SDIO_TX_AGG + prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; +#endif /* CFG_SDIO_TX_AGG */ + + // allocate MSDU_INFO_T and link it into rFreeMsduInfoList + QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList); + + pucMemHandle = prTxCtrl->pucTxCached; + for (i = 0 ; i < CFG_TX_MAX_PKT_NUM ; i++) { + prMsduInfo = (P_MSDU_INFO_T)pucMemHandle; + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T)); + } + + ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((UINT_32)(pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize); + + QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue); + prTxCtrl->i4TxMgmtPendingNum = 0; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum = 0; + prTxCtrl->u4TotalTxPacketNum = 0; +#endif + + prTxCtrl->i4PendingFwdFrameCount = 0; + + qmInit(prAdapter); + + TX_RESET_ALL_CNTS(prTxCtrl); + + return; +} /* end of nicTxInitialize() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will check if has enough TC Buffer for incoming +* packet and then update the value after promise to provide the resources. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucTC Specify the resource of TC +* +* \retval WLAN_STATUS_SUCCESS Resource is available and been assigned. +* \retval WLAN_STATUS_RESOURCES Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxAcquireResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ) +{ + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + +// DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) { + + prTxCtrl->rTc.aucFreeBufferCount[ucTC]--; + + DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n", + ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC])); + + u4Status = WLAN_STATUS_SUCCESS; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return u4Status; + +}/* end of nicTxAcquireResourceAndTFCBs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will do polling if FW has return the resource. +* Used when driver start up before enable interrupt. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Resource is available. +* @retval WLAN_STATUS_FAILURE Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxPollingResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ) +{ + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT; + UINT_32 au4WTSR[2]; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) { + return WLAN_STATUS_FAILURE; + } + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) { + return WLAN_STATUS_SUCCESS; + } + + while (i-- > 0) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) { + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } + } + else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } + } + +#if DBG + { + INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1); + + if (i4Times) { + DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n", + i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC))); + } + } +#endif /* DBG */ + + return u4Status; + +} /* end of nicTxPollingResource() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will release TC Buffer count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] u4TxStatusCnt Value of TX STATUS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +nicTxReleaseResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8* aucTxRlsCnt + ) +{ + PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt; + P_TX_CTRL_T prTxCtrl; + BOOLEAN bStatus = FALSE; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + // DBGLOG(TX, TRACE, ("\n")); + if (pu4Tmp[0] | pu4Tmp[1]) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = 0; i < TC_NUM; i++) { + prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i]; + + if ((i==1) || (i==5)){ + DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n", + i, prTxCtrl->rTc.aucFreeBufferCount[i])); + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + for (i = 0; i < TC_NUM; i++) { + DBGLOG(INIT, TRACE, ("aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n", + i, prTxCtrl->rTc.aucFreeBufferCount[i], i, prTxCtrl->rTc.aucMaxNumOfBuffer[i])); + } + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]); +#endif + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]); + bStatus = TRUE; + } + + return bStatus; +} /* end of nicTxReleaseResource() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset TC Buffer Count to initialized value +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxResetResource ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will return the value for other component +* which needs this information for making decisions +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval UINT_8 The number of corresponding TC number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +nicTxGetResource ( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucTC + ) +{ + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(prTxCtrl); + + if (ucTC >= TC_NUM) { + return 0; + } + else { + return prTxCtrl->rTc.aucFreeBufferCount[ucTC]; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll aggregate frame(PACKET_INFO_T) +* corresponding to HIF TX port +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoListHead a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxMsduInfoList ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort0, qDataPort1; + WLAN_STATUS status; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 + while(prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo); +#if DBG && 0 + LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prMsduInfo->ucTC, + prMsduInfo->ucNetworkType, + prMsduInfo->ucMacHeaderLength, + prMsduInfo->u2FrameLength, + prMsduInfo->ucPacketType, + prMsduInfo->fgIs802_1x, + prMsduInfo->fgIs802_11 ); + + LOG_FUNC("Dest Mac: " MACSTR "\n", + MAC2STR(prMsduInfo->aucEthDestAddr)); +#endif + + switch(prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + case TC5_INDEX: // Broadcast/multicast data packets + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo); + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + case TC4_INDEX: // Command or 802.1x packets + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo); + + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + if(qDataPort0.u4NumElem > 0) { + nicTxMsduQueue(prAdapter, 0, &qDataPort0); + } + + if(qDataPort1.u4NumElem > 0) { + nicTxMsduQueue(prAdapter, 1, &qDataPort1); + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucPortIdx Port Number +* @param prQue a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxMsduQueue ( + IN P_ADAPTER_T prAdapter, + UINT_8 ucPortIdx, + P_QUE_T prQue + ) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_16 u2OverallBufferLength; + UINT_8 ucEtherTypeOffsetInWord; + PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4TxHdrSize; + UINT_32 u4ValidBufSize; + UINT_32 u4TotalLength; + P_TX_CTRL_T prTxCtrl; + QUE_T rFreeQueue; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_8 ucChksumFlag; +#endif + + ASSERT(prAdapter); + ASSERT(ucPortIdx < 2); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + QUEUE_INITIALIZE(&rFreeQueue); + + if(prQue->u4NumElem > 0) { + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue); + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u4TotalLength = 0; + + while(prMsduInfo) { + + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + u4TxHdrSize = TX_HDR_SIZE; + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + } + else { + ucEtherTypeOffsetInWord = + ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + } + + rHwTxHeader.ucEtherTypeOffset = + ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prMsduInfo->eSrc == TX_PACKET_OS + || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | + CSUM_OFFLOAD_EN_TX_UDP | + CSUM_OFFLOAD_EN_TX_IP)) { + kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag); + + if (ucChksumFlag & TX_CS_IP_GEN) { + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM; + } + + if (ucChksumFlag & TX_CS_TCP_UDP_GEN) { + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM; + } + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = + (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if(prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } + else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if(prMsduInfo->fgIsBIP) { + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + } + + if(prMsduInfo->fgIsBasicRate) { + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; + } + +#if CFG_SDIO_TX_AGG + // attach to coalescing buffer + kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize); + u4TotalLength += u4TxHdrSize; + + if (prMsduInfo->eSrc == TX_PACKET_OS + || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + kalCopyFrame(prAdapter->prGlueInfo, + prNativePacket, + pucOutputBuf + u4TotalLength); + } + else if(prMsduInfo->eSrc == TX_PACKET_MGMT) { + kalMemCopy(pucOutputBuf + u4TotalLength, + prNativePacket, + prMsduInfo->u2FrameLength); + } + else { + ASSERT(0); + } + + u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength); + +#else + kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize); + + /* Copy Frame Body */ + if (prMsduInfo->eSrc == TX_PACKET_OS + || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + kalCopyFrame(prAdapter->prGlueInfo, + prNativePacket, + pucOutputBuf + u4TxHdrSize); + } + else if(prMsduInfo->eSrc == TX_PACKET_MGMT) { + kalMemCopy(pucOutputBuf + u4TxHdrSize, + prNativePacket, + prMsduInfo->u2FrameLength); + } + else { + ASSERT(0); + } + + ASSERT(u2OverallBufferLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32)u2OverallBufferLength, + (PUINT_8)pucOutputBuf, + u4ValidBufSize); + + // send immediately +#endif + prNextMsduInfo = (P_MSDU_INFO_T) + QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + else { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(INIT, TRACE,("Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum)); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } + else { + /* only free MSDU when it is not a MGMT frame */ + QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo); + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + kalSendComplete(prAdapter->prGlueInfo, + prNativePacket, + WLAN_STATUS_SUCCESS); + } + else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + } + + prMsduInfo = prNextMsduInfo; + } + +#if CFG_SDIO_TX_AGG + ASSERT(u4TotalLength <= u4ValidBufSize); + + #if CFG_DBG_GPIO_PINS + { + /* Start port write */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH); + } + #endif + + // send coalescing buffer + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + u4TotalLength, + (PUINT_8)pucOutputBuf, + u4ValidBufSize); +#endif + + // return + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue)); + } + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxCmd ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN UINT_8 ucTC + ) +{ + P_WIFI_CMD_T prWifiCmd; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_8 ucPortIdx; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_8 ucEtherTypeOffsetInWord; + P_MSDU_INFO_T prMsduInfo; + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + // <1> Assign Data Port + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } + else { + // Broadcast/multicast data frames, 1x frames, command packets, MMPDU + ucPortIdx = 1; + } + + if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + // <2> Compose HIF_TX_HEADER + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prCmdInfo->prPacket; + + ASSERT(prNativePacket); + + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + + rHwTxHeader.ucEtherTypeOffset = + ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET); + + rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK; + + rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = + (((UINT_8)(prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK); + + rHwTxHeader.u2SeqNo = 0; + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + + // <2.3> Copy HIF TX HEADER + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + // <3> Copy Frame Body Copy + kalCopyFrame(prAdapter->prGlueInfo, + prNativePacket, + pucOutputBuf + TX_HDR_SIZE); + } + else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + // <2> Compose HIF_TX_HEADER + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + ucEtherTypeOffsetInWord = + (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + + rHwTxHeader.ucEtherTypeOffset = + ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = + (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if(prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } + else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if(prMsduInfo->fgIsBIP) { + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + } + + if(prMsduInfo->fgIsBasicRate) { + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; + } + + // <2.3> Copy HIF TX HEADER + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + // <3> Copy Frame Body + kalMemCopy(pucOutputBuf + TX_HDR_SIZE, + prMsduInfo->prPacket, + prMsduInfo->u2FrameLength); + + // <4> Management Frame Post-Processing + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + else { + + DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } + else { + prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer; + + // <2> Compose the Header of Transmit Data Structure for CMD Packet + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW( + (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength; + prWifiCmd->ucEtherTypeOffset = 0; + prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET) + | (UINT_8)((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK)); + + + // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) + kalMemCopy((PVOID)&pucOutputBuf[0], + (PVOID)prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + } + + // <4> Write frame to data port + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32)u2OverallBufferLength, + (PUINT_8)pucOutputBuf, + (UINT_32)prAdapter->u4CoalescingBufCachedSize); + + return WLAN_STATUS_SUCCESS; +} /* end of nicTxCmd() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will clean up all the pending frames in internal SW Queues +* by return the pending TX packet to the system. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxRelease ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + nicTxFlush(prAdapter); + + // free MSDU_INFO_T from rTxMgmtMsduInfoList + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if(prMsduInfo) { + // the packet must be mgmt frame with tx done callback + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + ASSERT(prMsduInfo->pfTxDoneHandler != NULL); + + // invoke done handler + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + else { + break; + } + } while(TRUE); + + return; +} /* end of nicTxRelease() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process the TX Done interrupt and pull in more pending frames in SW +* Queues for transmission. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicProcessTxInterrupt( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; +#if CFG_SDIO_INTR_ENHANCE + P_SDIO_CTRL_T prSDIOCtrl; +#else + UINT_32 au4TxCount[2]; +#endif /* CFG_SDIO_INTR_ENHANCE */ + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prSDIOCtrl; + #if DBG + //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); + #endif + + nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo); + kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo)); + +#else + + HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]); + HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]); + DBGLOG(EMU, TRACE, ("MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1])); + + nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + // Indicate Service Thread + if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 + || wlanGetTxPendingFrameCount(prAdapter) > 0) { + kalSetEvent(prAdapter->prGlueInfo); + } + + return; +} /* end of nicProcessTxInterrupt() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function frees packet of P_MSDU_INFO_T linked-list +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxFreeMsduInfoPacket ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ) +{ + P_NATIVE_PACKET prNativePacket; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead; + P_TX_CTRL_T prTxCtrl; + + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while(prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + + if(prMsduInfo->eSrc == TX_PACKET_OS) { + kalSendComplete(prAdapter->prGlueInfo, + prNativePacket, + WLAN_STATUS_FAILURE); + } + else if(prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + } + cnmMemFree(prAdapter, prNativePacket); + } + else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo); + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxReturnMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while(prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo); + + switch(prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + + return; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function fills packet information to P_MSDU_INFO_T +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo P_MSDU_INFO_T +* @param prPacket P_NATIVE_PACKET +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +nicTxFillMsduInfo ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prPacket + ) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucPriorityParam; + UINT_8 ucMacHeaderLen; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen; + ULONG u4SysTime; + UINT_8 ucNetworkType; + + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, + &fgIsPAL, + &ucNetworkType) == FALSE) { + return FALSE; + } + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, ucPriorityParam); + + if (fgIs1x) { + GLUE_SET_PKT_FLAG_1X(prPacket); + } + + if (fgIsPAL) { + GLUE_SET_PKT_FLAG_PAL(prPacket); + } + + ucMacHeaderLen = ETH_HLEN; + + /* Save the value of Header Length */ + GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen); + + /* Save the value of Frame Length */ + GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen); + + /* Save the value of Arrival Time*/ + u4SysTime = (OS_SYSTIME)kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->fgIs802_1x = fgIs1x; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->ucNetworkType = ucNetworkType; + prMsduInfo->ucUserPriority = ucPriorityParam; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLen; + prMsduInfo->u2FrameLength = (UINT_16)u4PacketLen; + COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function update TCQ values by passing current status to txAdjustTcQuotas +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Updated successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxAdjustTcq ( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4Num; + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) { + prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num]; + prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num]; + + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0); + ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in STA/AC queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicTxFlush ( + IN P_ADAPTER_T prAdapter + ) +{ + P_MSDU_INFO_T prMsduInfo; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + // ask Per STA/AC queue to be fllushed and return all queued packets + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if(prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + return WLAN_STATUS_SUCCESS; +} + + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* However this function is used for INIT_CMD. +* +* In order to avoid further maintainance issues, these 2 functions are separated +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxInitCmd ( + IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN UINT_8 ucTC + ) +{ + P_INIT_HIF_TX_HEADER_T prInitTxHeader; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 ucPortIdx; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(ucTC == TC0_INDEX); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer; + + // <1> Compose the Header of Transmit Data Structure for CMD Packet + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW( + (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prInitTxHeader->u2TxByteCount = u2OverallBufferLength; + prInitTxHeader->ucEtherTypeOffset = 0; + prInitTxHeader->ucCSflags = 0; + + // <2> Assign Data Port + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } + else { // Broadcast/multicast data packets + ucPortIdx = 1; + } + + // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) + kalMemCopy((PVOID)&pucOutputBuf[0], + (PVOID)prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + // <4> Write frame to data port + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32)u2OverallBufferLength, + (PUINT_8)pucOutputBuf, + (UINT_32)prAdapter->u4CoalescingBufCachedSize); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll reset TX resource counter to initial value used +* in F/W download state +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxInitResetResource ( + IN P_ADAPTER_T prAdapter + ) +{ + P_TX_CTRL_T prTxCtrl; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + + return WLAN_STATUS_SUCCESS; + +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function enqueues MSDU_INFO_T into queue management, +* or command queue +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfo Pointer to MSDU +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicTxEnqueueMsdu ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead; + QUE_T qDataPort0, qDataPort1; + P_CMD_INFO_T prCmdInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + /* check how many management frame are being queued */ + while(prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo); + + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL; + + if(prMsduInfo->eSrc == TX_PACKET_MGMT) { + // MMPDU: force stick to TC4 + prMsduInfo->ucTC = TC4_INDEX; + + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo); + } + else { + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if(qDataPort0.u4NumElem) { + /* send to QM */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for dropped packets */ + if(prRetMsduInfo != NULL) { // unable to enqueue + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if(qDataPort1.u4NumElem) { + prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1); + + if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) { + // not enough descriptors for sending + u4Status = WLAN_STATUS_FAILURE; + + // free all MSDUs + while(prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + if (prMsduInfoHead->pfTxDoneHandler != NULL) { + prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER); + } + + + cnmMgtPktFree(prAdapter, prMsduInfoHead); + + prMsduInfoHead = prNextMsduInfo; + } + } + else { + /* send to command queue */ + while(prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = (P_NATIVE_PACKET)prMsduInfoHead; + prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex; + prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo); + } + else { + /* Cmd free count is larger than expected, but allocation fail. */ + ASSERT(0); + + u4Status = WLAN_STATUS_FAILURE; + cnmMgtPktFree(prAdapter, prMsduInfoHead); + } + + prMsduInfoHead = prNextMsduInfo; + } + } + } + + /* indicate service thread for sending */ + if(prTxCtrl->i4TxMgmtPendingNum > 0 + || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) { + kalSetEvent(prAdapter->prGlueInfo); + } + + return u4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function returns available count in command queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicTxGetFreeCmdCount ( + IN P_ADAPTER_T prAdapter + ) +{ + ASSERT(prAdapter); + + return prAdapter->rFreeCmdList.u4NumElem; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c new file mode 100755 index 000000000000..592318b00454 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c @@ -0,0 +1,203 @@ +/* +** $Id: @(#) p2p_nic.c@@ +*/ + +/*! \file p2p_nic.c + \brief Wi-Fi Direct Functions that provide operation in NIC's (Network Interface Card) point of view. + + This file includes functions which unite multiple hal(Hardware) operations + and also take the responsibility of Software Resource Management in order + to keep the synchronization with Hardware Manipulation. +*/ + + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, +* this function will be invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxAddP2pDevice ( + IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, + IN PUINT_8 pucRxIEBuf, + IN UINT_16 u2RxIELength + ) +{ + P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T)NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T)NULL; + UINT_32 u4Idx = 0; + BOOLEAN bUpdate = FALSE; + + PUINT_8 pucIeBuf = (PUINT_8)NULL; + UINT_16 u2IELength = 0; + UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + ASSERT(prAdapter); + + prP2pInfo = prAdapter->prP2pInfo; + + for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { + bUpdate = TRUE; + + /* Backup OLD buffer result. */ + pucIeBuf = prTargetResult->pucIeBuf; + u2IELength = prTargetResult->u2IELength; + + /* Update Device Info. */ + // zero + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + // then buffer + kalMemCopy(prTargetResult, + (PVOID)prP2pResult, + sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* See if new IE length is longer or not. */ + if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { + /* Buffer is not enough. */ + u2RxIELength = u2IELength; + } + else if ((u2IELength == 0) && (u2RxIELength != 0)) { + /* RX new IE buf. */ + ASSERT(pucIeBuf == NULL); + pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) > + (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2RxIELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is availabe. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } + else { + /* There is no new IE information, keep the old one. */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { /* whsu:XXX */ + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + // zero + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + // then buffer + kalMemCopy(prTargetResult, + (PVOID)prP2pResult, + sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + //printk("DVC FND %d " MACSTR", " MACSTR "\n", prP2pInfo->u4DeviceNum, MAC2STR(prP2pResult->aucDeviceAddr), MAC2STR(prTargetResult->aucDeviceAddr)); + + if (u2RxIELength) { + prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) > + (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2IELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr); + } + else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2IELength); + + kalMemCopy((PVOID)prTargetResult->pucIeBuf, (PVOID)pucRxIEBuf, (UINT_32)u2IELength); + prTargetResult->u2IELength = u2IELength; + } + else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } + else { + // TODO: Fixme to replace an old one. (?) + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c new file mode 100755 index 000000000000..9555bed85dce --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c @@ -0,0 +1,4802 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1 $ +*/ + +/*! \file "que_mgt.c" + \brief TX/RX queues management + + The main tasks of queue management include TC-based HIF TX flow control, + adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save + forwarding control, RX packet reordering, and RX BA agreement management. +*/ + + + +/* +** $Log: que_mgt.c $ + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 23 2012 eddie.chen + * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule + * Change the enqueue policy when ACM = 1. + * + * 11 22 2011 yuche.tsai + * NULL + * Code refine, remove one #if 0 code. + * + * 11 19 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for tx + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Fix xlog format to hex format + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug msg for xlog. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Use short name for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 10 2011 chinglan.wang + * NULL + * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP. + * + * 11 09 2011 chinglan.wang + * NULL + * [WiFi direct]Can't make P2P connect via PBC. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to the AP.. + * + * 10 25 2011 wh.su + * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check un-expect + * let the Rx BA accept even the sta not valid. + * + * 09 28 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * enlarge window size only by 4. + * + * 09 01 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * set rx window size as twice buffer size. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue. + * + * 08 03 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * force window size at least 16. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 26 2011 eddie.chen + * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter + * API for query the RX reorder queued packets counter. + * + * 07 07 2011 eddie.chen + * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. + * Add setEvent when free quota is updated. + * + * 07 05 2011 eddie.chen + * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. + * Send 1x when peer STA is in PS. + * + * 05 31 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Fix the QM quota in MT5931. + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 yuche.tsai + * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved) + * Deauthentication frame is not bound to network active status. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 28 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Fix Klockwork warning. + * + * 03 28 2011 eddie.chen + * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW + * Fix wmm parameters in beacon for BOW. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 02 23 2011 eddie.chen + * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap + * Fix parsing WMM INFO and bmp delivery bitmap definition. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Chnage GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Remove comments. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 14 2011 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * Allow 802.1x can be send even the net is not active due the drver / fw sync issue. + * + * 01 13 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * Fix typo and compile error. + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * Fix WMM parameter condition for STA + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * 1) Check Bss if support QoS before adding WMMIE + * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control + * + * 01 12 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Update MQM for WMM IE generation method + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add per STA flow control when STA is in PS mode + * + * 01 03 2011 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * update prStaRec->fgIsUapsdSupported flag. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * use the #14 and modify the add code for check MMPDU. + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * only MMPDU not check the netActive flag. + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * not check the netActive flag for mgmt . + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 08 30 2010 yarco.yang + * NULL + * Fixed klockwork error message + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 10 2010 yarco.yang + * NULL + * Code refine + * + * 08 06 2010 yarco.yang + * NULL + * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 20 2010 yarco.yang + * + * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 yarco.yang + * + * [WPD00003849] + * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * . + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Use fgInUse instead of fgIsValid for De-queue judgement + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * For MMPDU, STA_REC will be decided by caller module + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add MGMT Packet type for HIF_TX_HEADER + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Refined the debug msg + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * comment out one assertion which refer to undefined data member. + * + * 03 30 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled adaptive TC resource control + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * +* 03 17 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) + * + * 03 11 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed buffer leak when processing BAR frames + * + * 03 02 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5 + * + * 03 01 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed STA_REC index determination bug (fgIsValid shall be checked) + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Refined function qmDetermineStaRecIndex() for BMCAST packets + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled multi-STA TX path with fairness + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled dynamically activating and deactivating STA_RECs + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for dynamic activating and deactivating STA_RECs. + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the 802.1x path + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468 +** Fixed casting for qmAddRxBaEntry() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752 +** remove SD1_SD3.. flag +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468 +** Added RX buffer reordering functions +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468 +** Modified Flush Queue function to let queues be reinitialized +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468 +** Added flushing per-Type queues code +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468 +** Added Debug msgs and fixed incorrect assert +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468 +** Bug fixing (qmDequeueTxPackets local variable initialization) +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752 +** correct and surpress PREfast warning +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468 +** Used SD1_SD3_DATAPATH_INTEGRATION +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468 +** Initial version +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +__KAL_INLINE__ VOID +qmDetermineStaRecIndex( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ); + +__KAL_INLINE__ VOID +qmDequeueTxPacketsFromPerStaQueues( + IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, + IN UINT_8 ucCurrentAvailableQuota, + IN UINT_8 ucTotalQuota + ); + +__KAL_INLINE__ VOID +qmDequeueTxPacketsFromPerTypeQueues( + IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, + IN UINT_8 ucMaxNum + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Managment for TX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmInit( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 u4QueArrayIdx; + UINT_32 i; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + //DbgPrint("QM: Enter qmInit()\n"); +#if CFG_SUPPORT_QOS + prAdapter->rWifiVar.fgSupportQoS = TRUE; +#else + prAdapter->rWifiVar.fgSupportQoS = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_RX + prAdapter->rWifiVar.fgSupportAmpduRx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduRx = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_TX + prAdapter->rWifiVar.fgSupportAmpduTx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduTx = FALSE; +#endif + +#if CFG_SUPPORT_TSPEC + prAdapter->rWifiVar.fgSupportTspec = TRUE; +#else + prAdapter->rWifiVar.fgSupportTspec = FALSE; +#endif + +#if CFG_SUPPORT_UAPSD + prAdapter->rWifiVar.fgSupportUAPSD= TRUE; +#else + prAdapter->rWifiVar.fgSupportUAPSD = FALSE; +#endif + +#if CFG_SUPPORT_UL_PSMP + prAdapter->rWifiVar.fgSupportULPSMP = TRUE; +#else + prAdapter->rWifiVar.fgSupportULPSMP = FALSE; +#endif + + //4 <2> Initialize other TX queues (queues not in STA_RECs) + for(u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++){ + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx])); + } + + //4 <3> Initialize the RX BA table and RX queues + /* Initialize the RX Reordering Parameters and Queues */ + for(u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++){ + prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue)); + prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE; + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + //4 <4> Initialize TC resource control variables + for(i = 0; i < TC_NUM; i++){ + prQM->au4AverageQueLen[i] = 0; + } + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + +// ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); + + prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1)*/ + prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + + prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE; + prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE; + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; + prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE; + prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1)*/ + prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE; + + + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; + prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE; + prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE; + prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE; + + prQM->fgTcResourcePostAnnealing = FALSE; + + ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64); +#endif + +#if QM_TEST_MODE + prQM->u4PktCount = 0; + +#if QM_TEST_FAIR_FORWARDING + + prQM->u4CurrentStaRecIndexToEnqueue = 0; + { + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + P_STA_RECORD_T prStaRec; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + prStaRec = &prAdapter->arStaRec[1]; + ASSERT(prStaRec); + + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prStaRec->fgIsAp = TRUE; + COPY_MAC_ADDR((prStaRec)->aucMacAddr,aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS +{ + UINT_32 i; + for (i=0; i < NUM_OF_PER_STA_TX_QUEUES; i++){ + prQM->au4ForwardCount[i] = 0; + prQM->au4HeadStaRecIndex[i] = 0; + } +} +#endif + +} + +#if QM_TEST_MODE +VOID +qmTestCases( + IN P_ADAPTER_T prAdapter + ) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DbgPrint("QM: ** TEST MODE **\n"); + + if(QM_TEST_STA_REC_DETERMINATION){ + if(prAdapter->arStaRec[0].fgIsValid){ + prAdapter->arStaRec[0].fgIsValid = FALSE; + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + } + else{ + prAdapter->arStaRec[0].fgIsValid = TRUE; + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + } + } + + if(QM_TEST_STA_REC_DEACTIVATION){ + /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */ + + if(prAdapter->arStaRec[0].fgIsValid){ + + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + qmDeactivateStaRec(prAdapter,0); + } + else{ + + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + qmActivateStaRec( + prAdapter, /* Adapter pointer */ + 0, /* STA_REC index from FW */ + TRUE, /* fgIsQoS */ + NETWORK_TYPE_AIS_INDEX, /* Network type */ + TRUE, /* fgIsAp */ + aucMacAddr /* MAC address */ + ); + } + } + + if(QM_TEST_FAIR_FORWARDING){ + if(prAdapter->arStaRec[1].fgIsValid){ + prQM->u4CurrentStaRecIndexToEnqueue ++; + prQM->u4CurrentStaRecIndexToEnqueue %= 2; + DbgPrint("QM: (Test) Switch to STA_REC[%ld]\n", prQM->u4CurrentStaRecIndexToEnqueue); + } + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Activate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* \param[in] fgIsQoS Set to TRUE if this is a QoS STA +* \param[in] pucMacAddr The MAC address of the STA +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmActivateStaRec( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec + ) +{ + + //4 <1> Deactivate first + ASSERT(prStaRec); + + if(prStaRec->fgIsValid){ /* The STA_REC has been activated */ + DBGLOG(QM, WARN, ("QM: (WARNING) Activating a STA_REC which has been activated \n")); + DBGLOG(QM, WARN, ("QM: (WARNING) Deactivating a STA_REC before re-activating \n")); + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); // To flush TX/RX queues and del RX BA agreements + } + + //4 <2> Activate the STA_REC + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE;; + + /* Done in qmInit() or qmDeactivateStaRec() */ +#if 0 + /* At the beginning, no RX BA agreements have been established */ + for(i =0; iaprRxReorderParamRefTbl)[i] = NULL; + } +#endif + + DBGLOG(QM, INFO, ("QM: +STA[%ld]\n", prStaRec->ucIndex)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmDeactivateStaRec( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4StaRecIdx + ) +{ + P_STA_RECORD_T prStaRec; + UINT_32 i; + P_MSDU_INFO_T prFlushedTxPacketList = NULL; + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + //4<1> Flush TX queues + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx); + + if(prFlushedTxPacketList){ + wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList); + } + + //4 <2> Flush RX queues and delete RX BA agreements + for(i =0; i < CFG_RX_MAX_BA_TID_NUM; i++){ + /* Delete the RX BA entry with TID = i */ + qmDelRxBaEntry(prAdapter, (UINT_8)u4StaRecIdx, (UINT_8)i, FALSE); + } + + //4 <3> Deactivate the STA_REC + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + + DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the network +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID +qmFreeAllByNetType( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + + P_QUE_MGT_T prQM; + P_QUE_T prQue; + QUE_T rNeedToFreeQue; + QUE_T rTempQue; + P_QUE_T prNeedToFreeQue; + P_QUE_T prTempQue; + P_MSDU_INFO_T prMsduInfo; + + + prQM = &prAdapter->rQM; + prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + + QUEUE_INITIALIZE(&rNeedToFreeQue); + QUEUE_INITIALIZE(&rTempQue); + + prNeedToFreeQue = &rNeedToFreeQue; + prTempQue = &rTempQue; + + QUEUE_MOVE_ALL(prTempQue, prQue); + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + while (prMsduInfo) { + + if(prMsduInfo->ucNetworkType == eNetworkTypeIdx) { + QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T)prMsduInfo); + } + else { + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T)prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + } + if(QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) { + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(prNeedToFreeQue)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush all TX queues +* +* \param[in] (none) +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +qmFlushTxQueues( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_8 ucStaArrayIdx; + UINT_8 ucQueArrayIdx; + + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(QM, TRACE, ("QM: Enter qmFlushTxQueues()\n")); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for(ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++){ + + /* Always check each STA_REC when flushing packets no matter it is inactive or active */ + #if 0 + if(!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid){ + continue; /* Continue to check the next STA_REC */ + } + #endif + + for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){ + if(QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))){ + continue; /* Continue to check the next TX queue of the same STA */ + } + + if(!prMsduInfoListHead){ + + /* The first MSDU_INFO is found */ + prMsduInfoListHead =(P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail =(P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + else{ + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + } + + /* Flush per-Type queues */ + for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++){ + + if(QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))){ + continue; /* Continue to check the next TX queue of the same STA */ + } + + if(!prMsduInfoListHead){ + + /* The first MSDU_INFO is found */ + prMsduInfoListHead =(P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail =(P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } + else{ + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]); + + } + + if(prMsduInfoListTail){ + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL); + } + + return prMsduInfoListHead; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush TX packets for a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +qmFlushStaTxQueues( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4StaRecIdx + ) +{ + UINT_8 ucQueArrayIdx; + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if(!prStaRec->fgIsValid){ + return NULL; + } +#endif + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){ + if(QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))){ + continue; + } + + if(!prMsduInfoListHead){ + /* The first MSDU_INFO is found */ + prMsduInfoListHead =(P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail =(P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); } + else{ + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = + (P_MSDU_INFO_T)QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]); + + } + +#if 0 + if(prMsduInfoListTail){ + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx)); + } + else { + prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx); + } +#endif + + return prMsduInfoListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets +* +* \param[in] (none) +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T +qmFlushRxQueues( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i; + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, ("QM: Enter qmFlushRxQueues()\n")); + + for(i =0; iarRxBaTable[i].rReOrderQue))){ + if(!prSwRfbListHead){ + + /* The first MSDU_INFO is found */ + prSwRfbListHead =(P_SW_RFB_T) + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)); + prSwRfbListTail =(P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } + else{ + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail, + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue))); + + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + + } + else{ + continue; + } + } + + if(prSwRfbListTail){ + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets with respect to a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* \param[in] u4Tid TID +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T +qmFlushStaRxQueue( + IN P_ADAPTER_T prAdapter, + IN UINT_32 u4StaRecIdx, + IN UINT_32 u4Tid + ) +{ + //UINT_32 i; + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_RX_BA_ENTRY_T prReorderQueParm; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaRxQueues(%ld)\n", u4StaRecIdx)); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if(!prStaRec->fgIsValid){ + return NULL; + } +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ + if(prReorderQueParm){ + + if(QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))){ + + prSwRfbListHead =(P_SW_RFB_T) + QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue)); + prSwRfbListTail =(P_SW_RFB_T) + QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue)); + + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + + } + } + + if(prSwRfbListTail){ + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enqueue TX packets +* +* \param[in] prMsduInfoListHead Pointer to the list of TX packets +* +* \return The freed packets, which are not enqueued +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +qmEnqueueTxPackets( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfoListHead + ) +{ + P_MSDU_INFO_T prMsduInfoReleaseList; + P_MSDU_INFO_T prCurrentMsduInfo; + P_MSDU_INFO_T prNextMsduInfo; + + P_STA_RECORD_T prStaRec; + P_QUE_T prTxQue; + QUE_T rNotEnqueuedQue; + + + UINT_8 ucPacketType; + UINT_8 ucTC; + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK*/, 1 /*na*/, 0/*VItoBE*/ , 4 /*VOtoVI*/}; + + DBGLOG(QM, LOUD, ("Enter qmEnqueueTxPackets\n")); + + ASSERT(prMsduInfoListHead); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + { + //UINT_32 i; + //4 <0> Update TC resource control related variables + /* Keep track of the queue length */ + if (--prQM->u4TimeToUpdateQueLen == 0){ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + } + } +#endif + + /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */ + prStaRec = NULL; + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + + do{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgCheckACMAgain; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); + ucTC = TC1_INDEX; + + //4 <1> Lookup the STA_REC index + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + ucPacketType = HIF_TX_PACKET_TYPE_DATA; + + DBGLOG(QM, LOUD , ("***** ucStaRecIndex = %d *****\n", + prCurrentMsduInfo->ucStaRecIndex)); + + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]); + + if(IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) { + + switch (prCurrentMsduInfo->ucStaRecIndex){ + case STA_REC_INDEX_BMCAST: + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = TC5_INDEX; +#if 0 + if(prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX + && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT + ) { + if(LINK_IS_EMPTY(&prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) { + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl,TX_AP_BORADCAST_DROP); + } + } +#endif + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + ucTC = TC5_INDEX; + + if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + + /* if the packet is the forward type. the packet should be freed */ + DBGLOG(QM, TRACE, ("Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n")); + //prTxQue = &rNotEnqueuedQue; + } + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC]; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + + break; + + default: + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsValid); + + if(prCurrentMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15); + /* QM_DBG_CNT_15 */ /* QM_DBG_CNT_16 */ /* QM_DBG_CNT_17 */ /* QM_DBG_CNT_18 */ + /* QM_DBG_CNT_19 */ /* QM_DBG_CNT_20 */ /* QM_DBG_CNT_21 */ /* QM_DBG_CNT_22 */ + } + + eAci = WMM_AC_BE_INDEX; + do { + fgCheckACMAgain = FALSE; + if (prStaRec->fgIsQoS){ + switch(prCurrentMsduInfo->ucUserPriority){ + case 1: + case 2: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0]; + ucTC = TC0_INDEX; + eAci = WMM_AC_BK_INDEX; + break; + case 0: + case 3: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + break; + case 4: + case 5: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2]; + ucTC = TC2_INDEX; + eAci = WMM_AC_VI_INDEX; + break; + case 6: + case 7: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3]; + ucTC = TC3_INDEX; + eAci = WMM_AC_VO_INDEX; + break; + default: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + ASSERT(0); + break; + } + if(prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci != WMM_AC_BK_INDEX) { + prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } + else{ + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + } + } + while(fgCheckACMAgain); + + //LOG_FUNC ("QoS %u UP %u TC %u",prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); + + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if(prTxQue->u4NumElem > 32) { + DBGLOG(QM, INFO, ("Drop the Packet for full Tx queue (forwarding) Bss %u\n", prCurrentMsduInfo->ucNetworkType)); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl,TX_FORWARD_OVERFLOW_DROP); + } + } + + } + else { + + DBGLOG(QM, INFO, ("Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType)); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl,TX_INACTIVE_BSS_DROP); + } + + //4 <3> Fill the MSDU_INFO for constructing HIF TX header + + /* TODO: Fill MSDU_INFO according to the network type, + * EtherType, and STA status (for PS forwarding control). + */ + + /* Note that the Network Type Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET( + prCurrentMsduInfo, /* MSDU_INFO ptr */ + ucTC, /* TC tag */ + ucPacketType, /* Packet Type */ + 0, /* Format ID */ + prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */ + prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */ + 0, /* PAL LLH */ + 0, /* ACL SN */ + PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */ + 0 /* PS Session ID */ + ); + + //4 <4> Enqueue the packet + QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T)prCurrentMsduInfo); + + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT){ + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } + +#endif + + DBGLOG(QM, LOUD, ("Current queue length = %u\n", prTxQue->u4NumElem)); + }while(prNextMsduInfo); + + if( QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue) ) { + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rNotEnqueuedQue); + } + + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Determine the STA_REC index for a packet +* +* \param[in] prMsduInfo Pointer to the packet +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDetermineStaRecIndex( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + UINT_32 i; + + P_STA_RECORD_T prTempStaRec; + //P_QUE_MGT_T prQM = &prAdapter->rQM; + + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + //4 <1> DA = BMCAST + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)){ + /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP. + * FW shall take care of this. The host driver is not able to distinguish these cases. */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, ("TX with DA = BMCAST\n")); + return; + } + + + //4 <2> Check if an AP STA is present + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){ + prTempStaRec = &(prAdapter->arStaRec[i]); + + if((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)){ + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + + + + + //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){ + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsValid){ + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)){ + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + } + + + //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + DBGLOG(QM, LOUD, ("QM: TX with STA_REC_INDEX_NOT_FOUND\n")); + + +#if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING) + prMsduInfo->ucStaRecIndex = (UINT_8)prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a STA_REC for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerStaQueues( + IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, + IN UINT_8 ucCurrentQuota, + IN UINT_8 ucTotalQuota + ) +{ + +#if QM_FORWARDING_FAIRNESS + UINT_32 i; /* Loop for */ + + PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */ + PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */ + + P_STA_RECORD_T prStaRec; /* The current focused STA */ + P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */ + P_QUE_T prCurrQueue; /* The current TX queue to dequeue */ + P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */ + + UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */ + UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */ + UINT_32 u4Resource; /* The TX resource amount */ + + BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + PUINT_8 pucFreeQuota; + + DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC)); + + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || + ucTC == TC2_INDEX || ucTC == TC3_INDEX || + ucTC == TC4_INDEX + ); + + if(!ucCurrentQuota){ + DBGLOG(TX, LOUD, ("@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", + ucTC, ucCurrentQuota)); + return; + } + + u4Resource = ucCurrentQuota; + + //4 <1> Determine the head STA + /* The head STA shall be an active STA */ + + pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]); + pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]); + + DBGLOG(QM, LOUD, ("(Fairness) TID = %u Init Head STA = %u Resource = %u\n", + ucTC, *pu4HeadStaRecIndex, u4Resource)); + + + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + for (i=0; i < CFG_NUM_OF_STA_RECORD + 1; i++){ + prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)]; + ASSERT(prStaRec); + + /* Only Data frame (1x was not included) will be queued in */ + if (prStaRec->fgIsValid){ + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + /* Determine how many packets the head STA is allowed to send in a round */ + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25); + u4MaxForwardCount = ucTotalQuota; +#if CFG_ENABLE_WIFI_DIRECT + + pucFreeQuota = NULL; + if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + // TODO: Change the threshold in coorperation with the PS forwarding mechanism + // u4MaxForwardCount = ucTotalQuota; + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + + if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD*/) { + + if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } + else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } + else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } /* fgIsInPS */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) { + if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) { + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } + } + +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* Determine whether the head STA can continue to forward packets in this round */ + if((*pu4HeadStaRecForwardCount) < u4MaxForwardCount){ + break; + } + + } /* prStaRec->fgIsValid */ + else{ + /* The current Head STA has been deactivated, so search for a new head STA */ + prStaRec = NULL; + prBssInfo = NULL; + (*pu4HeadStaRecIndex) ++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + + /* Reset the forwarding count before searching (since this is for a new selected STA) */ + (*pu4HeadStaRecForwardCount) = 0; + } + } /* i < CFG_NUM_OF_STA_RECORD + 1 */ + + /* All STA_RECs are inactive, so exit */ + if (!prStaRec){ + /* Under concurrent, it is possible that there is no candidcated STA.*/ + //DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); + return; + } + + DBGLOG(QM, LOUD, ("(Fairness) TID = %u Round Head STA = %lu\n", + ucTC, *pu4HeadStaRecIndex)); + + //4 <2> Dequeue packets from the head STA + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + prDequeuedPkt = NULL; + fgChangeHeadSta = FALSE; + + while(prCurrQueue){ + + +#if QM_DEBUG_COUNTER + + if(ucTC <= TC4_INDEX) { + if(QUEUE_IS_EMPTY(prCurrQueue)) { + QM_DBG_CNT_INC(prQM, ucTC); + /* QM_DBG_CNT_00 */ /* QM_DBG_CNT_01 */ /* QM_DBG_CNT_02 */ /* QM_DBG_CNT_03 */ /* QM_DBG_CNT_04 */ + } + if(u4Resource == 0) { + QM_DBG_CNT_INC(prQM, ucTC + 5); + /* QM_DBG_CNT_05 */ /* QM_DBG_CNT_06 */ /* QM_DBG_CNT_07 */ /* QM_DBG_CNT_08 */ /* QM_DBG_CNT_09 */ + } + if(((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { + QM_DBG_CNT_INC(prQM, ucTC + 10); + /* QM_DBG_CNT_10 */ /* QM_DBG_CNT_11 */ /* QM_DBG_CNT_12 */ /* QM_DBG_CNT_13 */ /* QM_DBG_CNT_14 */ + } + } +#endif + + + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)){ + fgChangeHeadSta = TRUE; + break; + } + else if (u4Resource == 0){ + break; + } + else{ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); +#if DBG && 0 + LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, + prDequeuedPkt->fgIs802_1x, + prDequeuedPkt->fgIs802_11 ); + + LOG_FUNC("Dest Mac: " MACSTR "\n", + MAC2STR(prDequeuedPkt->aucEthDestAddr)); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket; + dumpMemory8((PUINT_8)prSkb->data,prSkb->len); + } +#endif + +#endif + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if(!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + } + + QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt); + u4Resource--; + (*pu4HeadStaRecForwardCount) ++; + + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + ASSERT(pucFreeQuota); + ASSERT(*pucFreeQuota>0); + if(*pucFreeQuota>0) { + *pucFreeQuota = *pucFreeQuota - 1; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) { + if(prBssInfo->ucBssFreeQuota>0) { + prBssInfo->ucBssFreeQuota--; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + } + + if (*pu4HeadStaRecForwardCount){ + DBGLOG(QM, LOUD, ("TC = %u Round Head STA = %lu, u4HeadStaRecForwardCount = %lu\n", ucTC, *pu4HeadStaRecIndex, (*pu4HeadStaRecForwardCount))); + } + +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (prDequeuedPkt){ + prDequeuedPkt->fgIsBurstEnd = TRUE; + } +#endif + + + //4 <3> Dequeue from the other STAs if there is residual TX resource + + /* Check all of the STAs to continue forwarding packets (including the head STA) */ + for (i= 0; i< CFG_NUM_OF_STA_RECORD; i++){ + /* Break in case no reasource is available */ + if (u4Resource == 0){ + break; + } + + /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */ + prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD]; + ASSERT(prStaRec); + + if (prStaRec->fgIsValid) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + DBGLOG(QM, LOUD, ("(Fairness) TID = %u Sharing STA = %u Resource = %lu\n", + ucTC, prStaRec->ucIndex, u4Resource)); + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + u4ForwardCount = 0; + u4MaxForwardCount = ucTotalQuota; + +#if CFG_ENABLE_WIFI_DIRECT + pucFreeQuota = NULL; + if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + // TODO: Change the threshold in coorperation with the PS forwarding mechanism + // u4MaxForwardCount = ucTotalQuota; + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD*/) { + + if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } + else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } + else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_WIFI_DIRECT + if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) { + if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) { + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } + } + +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } /* prStaRec->fgIsValid */ + else{ + prBssInfo = NULL; + /* Invalid STA, so check the next STA */ + continue; + } + + while(prCurrQueue){ + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)){ + break; + } + else{ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + +#if DBG && 0 + DBGLOG(QM, LOUD, ("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, + prDequeuedPkt->fgIs802_1x, + prDequeuedPkt->fgIs802_11 )); + + DBGLOG(QM, LOUD,("Dest Mac: " MACSTR "\n", + MAC2STR(prDequeuedPkt->aucEthDestAddr))); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket; + dumpMemory8((PUINT_8)prSkb->data,prSkb->len); + } +#endif + +#endif + + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if(!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + } + + QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt); + u4Resource--; + u4ForwardCount ++; + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + ASSERT(pucFreeQuota); + ASSERT(*pucFreeQuota>0); + if(*pucFreeQuota>0) { + *pucFreeQuota = *pucFreeQuota - 1; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + +#if CFG_ENABLE_WIFI_DIRECT + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) { + if(prBssInfo->ucBssFreeQuota>0) { + prBssInfo->ucBssFreeQuota--; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + } + +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (u4ForwardCount){ + prDequeuedPkt->fgIsBurstEnd = TRUE; + } +#endif + } + + + if (fgChangeHeadSta){ + (*pu4HeadStaRecIndex) ++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + (*pu4HeadStaRecForwardCount) = 0; + DBGLOG(QM, LOUD, ("(Fairness) TID = %u Scheduled Head STA = %lu Left Resource = %lu\n", + ucTC, (*pu4HeadStaRecIndex), u4Resource)); + } + + +/***************************************************************************************/ +#else + UINT_8 ucStaRecIndex; + P_STA_RECORD_T prStaRec; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + + DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC)); + + if (ucCurrentQuota == 0){ + return; + } + + //4 <1> Determine the queue index and the head STA + + /* The head STA */ + ucStaRecIndex = 0; /* TODO: Get the current head STA */ + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex); + ASSERT(prStaRec); + + if(prStaRec == NULL) { + return; + } + + /* The queue to pull out packets */ + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || + ucTC == TC2_INDEX || ucTC == TC3_INDEX || + ucTC == TC4_INDEX + ); + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + ucPktCount = ucCurrentQuota; + prDequeuedPkt = NULL; + + //4 <2> Dequeue packets for the head STA + while(TRUE){ + if (!(prStaRec->fgIsValid) || ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){ + break; + + } + else{ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + //DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); + ASSERT(prDequeuedPkt->ucTC == ucTC); + + QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt); + ucPktCount--; + } + } + + //DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); + +#if QM_BURST_END_INFO_ENABLED + if (prDequeuedPkt){ + prDequeuedPkt->fgIsBurstEnd = TRUE; + } + +#endif + + //4 <3> Update scheduling info + /* TODO */ + + //4 <4> Utilize the remainaing TX opportunities for non-head STAs + /* TODO */ +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a per-Type-based Queue for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (Shall always be TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerTypeQueues( + IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, + IN UINT_8 ucMaxNum + ) +{ + //UINT_8 ucQueIndex; + //UINT_8 ucStaRecIndex; + P_BSS_INFO_T prBssInfo; + P_BSS_INFO_T parBssInfo; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + P_MSDU_INFO_T prBurstEndPkt; + QUE_T rMergeQue; + P_QUE_T prMergeQue; + P_QUE_MGT_T prQM; + + DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum)); + + /* TC5: Broadcast/Multicast data packets */ + ASSERT(ucTC == TC5_INDEX); + + if (ucMaxNum == 0){ + return; + } + + prQM = &prAdapter->rQM; + //4 <1> Determine the queue + + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucPktCount = ucMaxNum; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + parBssInfo = prAdapter->rWifiVar.arBssInfo; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + //4 <2> Dequeue packets + while(TRUE){ + if(ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){ + break; + } + else{ + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + ASSERT(prDequeuedPkt->ucTC == ucTC); + + ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType]; + + if(IS_BSS_ACTIVE(prBssInfo)) { + if( !prBssInfo->fgIsNetAbsent){ + QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt); + prBurstEndPkt = prDequeuedPkt; + ucPktCount--; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); +#if DBG && 0 + LOG_FUNC("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, + prDequeuedPkt->fgIs802_1x, + prDequeuedPkt->fgIs802_11 ); + + LOG_FUNC("Dest Mac: " MACSTR "\n", + MAC2STR(prDequeuedPkt->aucEthDestAddr)); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket; + dumpMemory8((PUINT_8)prSkb->data,prSkb->len); + } +#endif + +#endif + } + else { + QUEUE_INSERT_TAIL(prMergeQue,(P_QUE_ENTRY_T)prDequeuedPkt); + } + } + else { + QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL); + wlanProcessQueuedMsduInfo(prAdapter,prDequeuedPkt); + } + } + } + + if(QUEUE_IS_NOT_EMPTY(prMergeQue)) { + QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue); + QUEUE_MOVE_ALL(prCurrQueue, prMergeQue); + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(prCurrQueue), NULL); + } + +#if QM_BURST_END_INFO_ENABLED + if (prBurstEndPkt){ + prBurstEndPkt->fgIsBurstEnd = TRUE; + } +#endif +} /* qmDequeueTxPacketsFromPerTypeQueues */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets to send to HIF TX +* +* \param[in] prTcqStatus Info about the maximum amount of dequeued packets +* +* \return The list of dequeued TX packets +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T +qmDequeueTxPackets( + IN P_ADAPTER_T prAdapter, + IN P_TX_TCQ_STATUS_T prTcqStatus + ) +{ + + INT_32 i; + P_MSDU_INFO_T prReturnedPacketListHead; + QUE_T rReturnedQue; + + DBGLOG(QM, LOUD, ("Enter qmDequeueTxPackets\n")); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */ + for(i = TC4_INDEX; i >= TC0_INDEX; i--){ + DBGLOG(QM, LOUD, ("Dequeue packets from Per-STA queue[%u]\n", i)); + + qmDequeueTxPacketsFromPerStaQueues( + prAdapter, + &rReturnedQue, + (UINT_8)i, + prTcqStatus->aucFreeBufferCount[i], + prTcqStatus->aucMaxNumOfBuffer[i] + ); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, LOUD, ("DQA)[%u](%lu)\n", i, rReturnedQue.u4NumElem)); + } + + + /* TC5 (BMCAST or STA-NOT-FOUND packets) */ + qmDequeueTxPacketsFromPerTypeQueues( + prAdapter, + &rReturnedQue, + TC5_INDEX, + prTcqStatus->aucFreeBufferCount[TC5_INDEX] + ); + + DBGLOG(QM, LOUD, ("Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem)); + + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)){ + prReturnedPacketListHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rReturnedQue); + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return prReturnedPacketListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Adjust the TC quotas according to traffic demands +* +* \param[out] prTcqAdjust The resulting adjustment +* \param[in] prTcqStatus Info about the current TC quotas and counters +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmAdjustTcQuotas ( + IN P_ADAPTER_T prAdapter, + OUT P_TX_TCQ_ADJUST_T prTcqAdjust, + IN P_TX_TCQ_STATUS_T prTcqStatus + ) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Must initialize */ + for (i = 0; i < TC_NUM; i++){ + prTcqAdjust->acVariation[i]= 0; + } + + //4 <1> If TC resource is not just adjusted, exit directly + if (!prQM->fgTcResourcePostAnnealing){ + return; + } + + //4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource + else{ + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < TC_NUM; i++){ + ai4ExtraQuota[i] = (INT_32)prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32)prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0){ /* The resource shall be reallocated to other TCs */ + if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]){ + ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ + for (i = 0; i < TC_NUM; i++){ + if (ai4ExtraQuota[i] < 0){ + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota){ + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_PRINT_TC_RESOURCE_CTRL + DBGLOG(QM, LOUD, ("QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n", + prTcqStatus->aucFreeBufferCount[0], + prTcqStatus->aucFreeBufferCount[1], + prTcqStatus->aucFreeBufferCount[2], + prTcqStatus->aucFreeBufferCount[3], + prTcqStatus->aucFreeBufferCount[4], + prTcqStatus->aucFreeBufferCount[5] + )); +#endif + } + +#else + UINT_32 i; + for (i = 0; i < TC_NUM; i++){ + prTcqAdjust->acVariation[i]= 0; + } + +#endif +} + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update the average TX queue length for the TC resource control mechanism +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmUpdateAverageTxQueLen( + IN P_ADAPTER_T prAdapter + ) +{ + INT_32 u4CurrQueLen, i, k; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + //4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++){ + u4CurrQueLen = 0; + + for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++){ + prStaRec = &prAdapter->arStaRec[k]; + ASSERT(prStaRec); + + /* If the STA is activated, get the queue length */ + if (prStaRec->fgIsValid && + (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent) + ) + { + + u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem); + } + } + + if (prQM->au4AverageQueLen[i] == 0){ + prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } + else{ + prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[i] += (u4CurrQueLen); + } + + } + + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC_NUM-1] == 0){ + prQM->au4AverageQueLen[TC_NUM-1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } + else{ + prQM->au4AverageQueLen[TC_NUM-1] -= (prQM->au4AverageQueLen[TC_NUM-1] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC_NUM-1] += (u4CurrQueLen); + } + + + //4 <2> Adjust TC resource assignment + /* Check whether it is time to adjust the TC resource assignment */ + if (--prQM->u4TimeToAdjustTcResource == 0){ + /* The last assignment has not been completely applied */ + if (prQM->fgTcResourcePostAnnealing){ + /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */ + prQM->u4TimeToAdjustTcResource = 1; + } + + /* The last assignment has been applied */ + else{ + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + qmReassignTcResource(prAdapter); + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + for (i=0; i= 100){ + DBGLOG(QM, LOUD, ("QM: QueLen [%ld %ld %ld %ld %ld %ld]\n", + QM_GET_TX_QUEUE_LEN(prAdapter, 0), + QM_GET_TX_QUEUE_LEN(prAdapter, 1), + QM_GET_TX_QUEUE_LEN(prAdapter, 2), + QM_GET_TX_QUEUE_LEN(prAdapter, 3), + QM_GET_TX_QUEUE_LEN(prAdapter, 4), + QM_GET_TX_QUEUE_LEN(prAdapter, 5) + )); + break; + } + } +#endif + +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Assign TX resource for each TC according to TX queue length and current assignment +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmReassignTcResource( + IN P_ADAPTER_T prAdapter + ) +{ + INT_32 i4TotalResourceDemand = 0; + UINT_32 u4ResidualResource = 0; + UINT_32 i; + INT_32 ai4PerTcResourceDemand[TC_NUM]; + UINT_32 u4ShareCount = 0; + UINT_32 u4Share = 0 ; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to + * start the TC-quota adjusting procedure, which will be invoked upon every TX Done + */ + + //4 <1> Determine the demands + /* Determine the amount of extra resource to fulfill all of the demands */ + for (i=0; iau4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, i)){ + ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; + } + + i4TotalResourceDemand += ai4PerTcResourceDemand[i]; + } + + //4 <2> Case 1: Demand <= Total Resource + if (i4TotalResourceDemand <= 0){ + //4 <2.1> Satisfy every TC + for (i = 0; i < TC_NUM; i++){ + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) { + continue; + } + + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + } + + //4 <2.2> Share the residual resource evenly + u4ShareCount= (TC_NUM - 1); /* excluding TC4 */ + u4ResidualResource = (UINT_32)(-i4TotalResourceDemand); + u4Share = (u4ResidualResource/u4ShareCount); + + for (i=0; iau4CurrentTcResource[i] += u4Share; + + /* Every TC is fully satisfied */ + ai4PerTcResourceDemand[i] = 0; + + /* The left resource will be allocated to TC3 */ + u4ResidualResource -= u4Share; + } + + //4 <2.3> Allocate the left resource to TC3 (VO) + prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource); + + } + + //4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC + else{ + u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE; + + //4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand) + for (i=0; iau4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < prQM->au4GuaranteedTcResource[i]){ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + u4ResidualResource += (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + ai4PerTcResourceDemand[i] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else{ + ai4PerTcResourceDemand[i] -= (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i]; + u4ShareCount++; + } + } + + //4 <3.2> Allocate the residual resource + do{ + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0){ + break; + } + + /* This shall not happen */ + if (u4ShareCount == 0){ + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, ("QM: (Error) u4ShareCount = 0\n")); + break; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + if(u4Share){ + for (i=0; iau4CurrentTcResource[i] += u4Share; + u4ResidualResource -= u4Share; + ai4PerTcResourceDemand[i] -= u4Share; + } + else{ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + u4ResidualResource -= ai4PerTcResourceDemand[i]; + ai4PerTcResourceDemand[i] = 0; + } + } + } + } + + /* By priority, allocate the left resource that is not divisible by u4Share */ + if (u4ResidualResource == 0){ + break; + } + + if (ai4PerTcResourceDemand[TC3_INDEX]){ /* VO */ + prQM->au4CurrentTcResource[TC3_INDEX]++; + if (--u4ResidualResource == 0) { + break; + } + } + + if (ai4PerTcResourceDemand[TC2_INDEX]){ /* VI */ + prQM->au4CurrentTcResource[TC2_INDEX]++; + if (--u4ResidualResource == 0) { + break; + } + } + + if (ai4PerTcResourceDemand[TC5_INDEX]){ /* BMCAST */ + prQM->au4CurrentTcResource[TC5_INDEX]++; + if (--u4ResidualResource == 0) { + break; + } + } + + if (ai4PerTcResourceDemand[TC1_INDEX]){ /* BE */ + prQM->au4CurrentTcResource[TC1_INDEX]++; + if (--u4ResidualResource == 0) { + break; + } + } + + if (ai4PerTcResourceDemand[TC0_INDEX]){ /* BK */ + prQM->au4CurrentTcResource[TC0_INDEX]++; + if (--u4ResidualResource == 0) { + break; + } + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + }while(FALSE); + } + + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, LOUD, ("QM: TC Rsc %ld %ld %ld %ld %ld %ld\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], + prQM->au4CurrentTcResource[5] + )); +#endif + +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Managment for RX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmInitRxQueues( + IN P_ADAPTER_T prAdapter + ) +{ + //DbgPrint("QM: Enter qmInitRxQueues()\n"); + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle RX packets (buffer reordering) +* +* \param[in] prSwRfbListHead The list of RX packets +* +* \return The list of packets which are not buffered for reordering +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T +qmHandleRxPackets( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfbListHead + ) +{ + +#if CFG_RX_REORDERING_ENABLED + //UINT_32 i; + P_SW_RFB_T prCurrSwRfb; + P_SW_RFB_T prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + QUE_T rReturnedQue; + PUINT_8 pucEthDestAddr; + + //DbgPrint("QM: Enter qmHandleRxPackets()\n"); + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + QUEUE_INITIALIZE(&rReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do{ + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + prHifRxHdr = prCurrSwRfb->prHifRxHdr; // TODO: (Tehuang) Use macro to obtain the pointer + + /* TODO: (Tehuang) Check if relaying */ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST; + + /* Decide the Destination */ +#if CFG_RX_PKTS_DUMP + if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) { + DBGLOG(SW4, INFO, ("QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n", + HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), + prHifRxHdr->ucStaRecIdx, + prCurrSwRfb->ucWlanIdx, + HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ + HIF_RX_HDR_GET_TID(prHifRxHdr), + prCurrSwRfb->ucPacketType, + HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr))); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); + } +#endif + // DBGLOG(RX, TRACE, ("SN=%d, TID=%d\n", HIF_RX_HDR_GET_SN(prHifRxHdr), HIF_RX_HDR_GET_TID(prHifRxHdr))); + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ + + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + //DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); + // + + if( prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem + > (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM) ) { + + if(IS_BSS_ACTIVE(prBssInfo)) { + if(OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) { + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)){ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } + else if(UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr,pucEthDestAddr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD; + /* TODO : need to check the dst mac is valid */ + /* If src mac is invalid, the packet will be freed in fw */ + } + } /* OP_MODE_ACCESS_POINT */ + } + else { + DBGLOG(QM, TRACE, ("Mark NULL the Packet for inactive Bss %u\n",ucNetTypeIdx)); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); + continue; + } + + } + else { + /* Dont not occupy other SW RFB */ + DBGLOG(QM, TRACE, ("Mark NULL the Packet for less Free Sw Rfb\n")); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); + continue; + } + + } + + /* BAR frame */ + if(HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)){ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue); + } + /* Reordering is not required for this packet, return it without buffering */ + else if(!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr)){ +#if 0 + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)){ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } + } +#endif + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); + } + /* Reordering is required for this packet */ + else{ + /* If this packet should dropped or indicated to the host immediately, + * it should be enqueued into the rReturnedQue with specific flags. If + * this packet should be buffered for reordering, it should be enqueued + * into the reordering queue in the STA_REC rather than into the + * rReturnedQue. + */ + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue); + + } + }while(prNextSwRfb); + + + /* The returned list of SW_RFBs must end with a NULL pointer */ + if(QUEUE_IS_NOT_EMPTY(&rReturnedQue)){ + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T)QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return (P_SW_RFB_T)QUEUE_GET_HEAD(&rReturnedQue); + +#else + + //DbgPrint("QM: Enter qmHandleRxPackets()\n"); + return prSwRfbListHead; + +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reorder the received packet +* +* \param[in] prSwRfb The RX packet to process +* \param[out] prReturnedQue The queue for indicating packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmProcessPktWithReordering( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT P_QUE_T prReturnedQue + ) +{ + + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SeqNo; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + //P_SW_RFB_T prReorderedSwRfb; + + DEBUGFUNC("qmProcessPktWithReordering"); + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prHifRxHdr); + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */ + prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr)); + //prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + + /* Incorrect STA_REC index */ + if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + DBGLOG(QM, WARN,("Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", + prSwRfb->ucStaRecIdx)); + //ASSERT(0); + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if(!(prStaRec->fgIsValid)){ + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + DBGLOG(QM, WARN, ("Reordering for an invalid STA_REC \n")); + //ASSERT(0); + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if(!prReorderQueParm){ + /* TODO: (Tehuang) Handle the Host-FW sync issue.*/ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + DBGLOG(QM, WARN,("Reordering for a NULL ReorderQueParm \n")); + //ASSERT(0); + return; + } + + + + /* Start to reorder packets */ + u4SeqNo = (UINT_32)(prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd); + + /* Debug */ + //DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + /* Case 1: Fall within */ + if /* 0 - start - sn - end - 4095 */ + (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd)) + /* 0 - end - start - sn - 4095 */ + || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo)) + /* 0 - sn - end - start - 4095 */ + || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))){ + + qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if(prReorderQueParm->fgIsWaitingForPktWithSsn){ + /* Let the first received packet pass the reorder check */ + DBGLOG(QM, LOUD, ("QM:(A)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd)); + + prReorderQueParm->u2WinStart = (UINT_16)u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; + } +#endif + + + qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue); + } + /* Case 2: Fall ahead */ + else if + /* 0 - start - end - sn - (start+2048) - 4095 */ + (((u4WinStart < u4WinEnd) + && (u4WinEnd < u4SeqNo) + && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - sn - (start+2048) - start - end - 4095 */ + || ((u4SeqNo < u4WinStart) + && (u4WinStart < u4WinEnd) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - end - sn - (start+2048) - start - 4095 */ + || ((u4WinEnd < u4SeqNo) + && (u4SeqNo < u4WinStart) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))){ + + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if(prReorderQueParm->fgIsWaitingForPktWithSsn){ + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; + } +#endif + + qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (UINT_16)u4SeqNo; + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1) + % MAX_SEQ_NO_COUNT); + + qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); + + } + /* Case 3: Fall behind */ + else{ + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + #if QM_RX_INIT_FALL_BEHIND_PASS + if(prReorderQueParm->fgIsWaitingForPktWithSsn){ + //?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + //DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + return; + } + #endif +#endif + + /* An erroneous packet */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + //DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + return; + } + + return; + +} + + +VOID +qmProcessBarFrame( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + OUT P_QUE_T prReturnedQue + ) +{ + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SSN; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + //P_SW_RFB_T prReorderedSwRfb; + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prHifRxHdr); + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */ + prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr)); + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + + /* Incorrect STA_REC index */ + if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){ + DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", + prSwRfb->ucStaRecIdx)); + //ASSERT(0); + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if(!(prStaRec->fgIsValid)){ + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + DbgPrint("QM: (Warning) BAR for an invalid STA_REC \n"); + //ASSERT(0); + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if(!prReorderQueParm){ + /* TODO: (Tehuang) Handle the Host-FW sync issue.*/ + DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL ReorderQueParm \n")); + //ASSERT(0); + return; + } + + + u4SSN = (UINT_32)(prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd); + + if(qmCompareSnIsLessThan(u4WinStart,u4SSN)){ + prReorderQueParm->u2WinStart = (UINT_16)u4SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + DBGLOG(QM, TRACE, ("QM:(BAR)[%d](%ld){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd)); + qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); + } + else{ + DBGLOG(QM, TRACE, ("QM:(BAR)(%d)(%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd)); + } +} + + + +VOID +qmInsertFallWithinReorderPkt( + IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ) +{ + P_SW_RFB_T prExaminedQueuedSwRfb; + P_QUE_T prReorderQue; + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue); + + /* There are no packets queued in the Reorder Queue */ + if(prExaminedQueuedSwRfb == NULL){ + ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL; + ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL; + prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb; + prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb; + prReorderQue->u4NumElem ++; + } + + /* Determine the insert position */ + else{ + do{ + /* Case 1: Terminate. A duplicate packet */ + if(((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))){ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb); + return; + } + + /* Case 2: Terminate. The insert point is found */ + else if(qmCompareSnIsLessThan( + (prSwRfb->u2SSN),(prExaminedQueuedSwRfb->u2SSN))){ + break; + } + + /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */ + else{ + prExaminedQueuedSwRfb = + (P_SW_RFB_T)(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prNext); + } + }while(prExaminedQueuedSwRfb); + + /* Update the Reorder Queue Parameters according to the found insert position */ + if(prExaminedQueuedSwRfb == NULL){ + /* The received packet shall be placed at the tail */ + ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail; + ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb); + prReorderQue->prTail = (P_QUE_ENTRY_T)(prSwRfb); + } + else{ + ((P_QUE_ENTRY_T)prSwRfb)->prPrev = ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev; + ((P_QUE_ENTRY_T)prSwRfb)->prNext = (P_QUE_ENTRY_T)prExaminedQueuedSwRfb; + if(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb) == (prReorderQue->prHead)){ + /* The received packet will become the head */ + prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb; + } + else{ + (((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T)prSwRfb; + } + ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T)prSwRfb; + } + + prReorderQue->u4NumElem ++; + + } + +} + + +VOID +qmInsertFallAheadReorderPkt( + IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ) +{ + P_QUE_T prReorderQue; + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + /* There are no packets queued in the Reorder Queue */ + if(QUEUE_IS_EMPTY(prReorderQue)){ + ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL; + ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL; + prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb; + } + else{ + ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail; + ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb); + } + prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb; + prReorderQue->u4NumElem ++; + +} + + +VOID +qmPopOutDueToFallWithin( + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead, fgMissing; + OS_SYSTIME rCurrentTime, *prMissTimeout; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + fgMissing = FALSE; + rCurrentTime = 0; + prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]); + if ((*prMissTimeout)){ + fgMissing = TRUE; + GET_CURRENT_SYSTIME(&rCurrentTime); + } + + /* Check whether any packet can be indicated to the higher layer */ + while(TRUE){ + if(QUEUE_IS_EMPTY(prReorderQue)){ + break; + } + + /* Always examine the head packet */ + prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){ + + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT); + } + /* SN > WinStart, break to update WinEnd */ + else{ + if ((fgMissing == TRUE) && + CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout), + MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) { + DBGLOG(QM, TRACE, ("QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2SSN)); + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT); + + fgMissing = FALSE; + } + else break; + } + + + /* Dequeue the head packet */ + if(fgDequeuHead){ + + if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){ + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } + else{ + prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem --; + //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb); + } + } + + if (QUEUE_IS_EMPTY(prReorderQue)){ + *prMissTimeout = 0; + } + else { + if (fgMissing == FALSE) { + GET_CURRENT_SYSTIME(prMissTimeout); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1 )% MAX_SEQ_NO_COUNT); + +} + +VOID +qmPopOutDueToFallAhead( + IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue + ) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + /* Check whether any packet can be indicated to the higher layer */ + while(TRUE){ + if(QUEUE_IS_EMPTY(prReorderQue)){ + break; + } + + /* Always examine the head packet */ + prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){ + + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT); + } + + /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */ + else if(qmCompareSnIsLessThan( + (UINT_32)(prReorderedSwRfb->u2SSN), + (UINT_32)(prReorderQueParm->u2WinStart))){ + + fgDequeuHead = TRUE; + + } + + /* SN > WinStart, break to update WinEnd */ + else{ + break; + } + + + /* Dequeue the head packet */ + if(fgDequeuHead){ + + if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){ + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } + else{ + prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem --; + //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); + QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1)% MAX_SEQ_NO_COUNT); + +} + +BOOLEAN +qmCompareSnIsLessThan( + IN UINT_32 u4SnLess, + IN UINT_32 u4SnGreater + ) +{ + /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ + if((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater){ /* Shall be <= */ + return FALSE; + } + + /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */ + else if((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess){ + return TRUE; + } + + /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */ + /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */ + else{ + return (u4SnLess < u4SnGreater); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle Mailbox RX messages +* +* \param[in] prMailboxRxMsg The received Mailbox message from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleMailboxRxMessage( + IN MAILBOX_MSG_T prMailboxRxMsg + ) +{ + //DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); + /* TODO */ +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle ADD RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleEventRxAddBa( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_RX_ADDBA_T prEventRxAddBa; + P_STA_RECORD_T prStaRec; + UINT_32 u4Tid; + UINT_32 u4WinSize; + + DBGLOG(QM, INFO, ("QM:Event +RxBa\n")); + + prEventRxAddBa = (P_EVENT_RX_ADDBA_T)prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx); + + if(!prStaRec){ + /* Invalid STA_REC index, discard the event packet */ + //ASSERT(0); + DBGLOG(QM, INFO, ("QM: (Warning) RX ADDBA Event for a NULL STA_REC\n")); + return; + } + +#if 0 + if(!(prStaRec->fgIsValid)){ + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + DBGLOG(QM, WARN, ("QM: (Warning) RX ADDBA Event for an invalid STA_REC\n")); + //ASSERT(0); + //return; + } +#endif + + u4Tid = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_TID_MASK) + >> BA_PARAM_SET_TID_MASK_OFFSET); + + u4WinSize = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + if(!qmAddRxBaEntry( + prAdapter, + prStaRec->ucIndex, + (UINT_8)u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), + (UINT_16)u4WinSize)){ + + /* FW shall ensure the availabiilty of the free-to-use BA entry */ + DBGLOG(QM, ERROR, ("QM: (Error) qmAddRxBaEntry() failure\n")); + ASSERT(0); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle DEL RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleEventRxDelBa( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_RX_DELBA_T prEventRxDelBa; + P_STA_RECORD_T prStaRec; + + //DbgPrint("QM:Event -RxBa\n"); + + prEventRxDelBa = (P_EVENT_RX_DELBA_T)prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx); + + if(!prStaRec){ + /* Invalid STA_REC index, discard the event packet */ + //ASSERT(0); + return; + } + +#if 0 + if(!(prStaRec->fgIsValid)){ + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + //ASSERT(0); + return; + } +#endif + + qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE); + +} + +P_RX_BA_ENTRY_T +qmLookupRxBaEntry( + IN P_ADAPTER_T prAdapter, + UINT_8 ucStaRecIdx, + UINT_8 ucTid + ) +{ + int i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + //DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); + + for(i=0; iarRxBaTable[i].fgIsValid){ + if((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && + (prQM->arRxBaTable[i].ucTid == ucTid)){ + return &prQM->arRxBaTable[i]; + } + } + } + return NULL; +} + +BOOL +qmAddRxBaEntry( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, + IN UINT_8 ucTid, + IN UINT_16 u2WinStart, + IN UINT_16 u2WinSize + ) +{ + int i; + P_RX_BA_ENTRY_T prRxBaEntry = NULL; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); + + if(ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){ + /* Invalid STA_REC index, discard the event packet */ + DBGLOG(QM, WARN, ("QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx)); + return FALSE; + } + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + + //if(!(prStaRec->fgIsValid)){ + // DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA \n"); + // return FALSE; + //} + + //4 <1> Delete before adding + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + if(qmLookupRxBaEntry(prAdapter, ucStaRecIdx,ucTid)){ + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */ + } + + //4 <2> Add a new BA entry + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if(prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS){ + DBGLOG(QM, ERROR, ("QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount)); + return FALSE; + } + else{ + /* Find the free-to-use BA entry */ + for(i=0; iarRxBaTable[i].fgIsValid){ + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, ("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount)); + break; + } + } + + /* If a free-to-use entry is found, configure it and associate it with the STA_REC */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if(prRxBaEntry){ + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize= u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT); + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + + g_arMissTimeout[ucStaRecIdx][ucTid] = 0; + + DBGLOG(QM, INFO, ("QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n", + ucStaRecIdx, ucTid, + prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize)); + + /* Update the BA entry reference table for per-packet lookup */ + prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry; + } + else{ + /* This shall not happen because FW should keep track of the usage of RX BA entries */ + DBGLOG(QM, ERROR, ("QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount)); + return FALSE; + } + } + + return TRUE; +} +VOID +qmDelRxBaEntry( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, + IN UINT_8 ucTid, + IN BOOLEAN fgFlushToHost + ) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prFlushedPacketList = NULL; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + +#if 0 + if(!(prStaRec->fgIsValid)){ + DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA \n"); + return; + } +#endif + + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid]; + + if(prRxBaEntry){ + + prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid); + + if(prFlushedPacketList){ + + if(fgFlushToHost) { + wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList); + } + else { + + P_SW_RFB_T prSwRfb; + P_SW_RFB_T prNextSwRfb; + prSwRfb = prFlushedPacketList; + + do { + prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + prSwRfb = prNextSwRfb; + } while(prSwRfb); + + } + + + } +#if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0)) + /* Update RX BA entry state. Note that RX queue flush is not done here */ + prRxBaEntry->fgIsValid = FALSE; + prQM->ucRxBaCount--; + + /* Debug */ + #if 0 + DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + #endif + + /* Update STA RX BA table */ + prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL; +#endif + + DBGLOG(QM, INFO, ("QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid)); + + } + + + /* Debug */ + #if CFG_HIF_RX_STARVATION_WARNING + { + P_RX_CTRL_T prRxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + DBGLOG(QM, TRACE, ("QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt)); + } + #endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmProcessAssocReq ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_IE_WMM_INFO_T prIeWmmInfo; + + DEBUGFUNC("mqmProcessAssocReq"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(prStaRec == NULL) { + return; + } + + prStaRec->fgIsQoS = FALSE; + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + pucIEStart = pucIE; + + /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/ + if (!prAdapter->rWifiVar.fgSupportQoS) { + return; + } + + + /* Determine whether QoS is enabled with the association */ + else{ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + + if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){ + + switch(WMM_IE_OUI_SUBTYPE(pucIE)){ + case VENDOR_OUI_SUBTYPE_WMM_INFO: + { + + UINT_8 ucQosInfo; + UINT_8 ucQosInfoAC; + UINT_8 ucBmpAC; + if(IE_LEN(pucIE) != 7){ + break; /* WMM Info IE with a wrong length */ + } + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (P_IE_WMM_INFO_T)pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + prStaRec->fgIsUapsdSupported = ((ucQosInfoAC)? TRUE: FALSE) & + prAdapter->rWifiVar.fgSupportUAPSD; + + ucBmpAC = 0; + + if( ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) { + ucBmpAC |= BIT(ACI_VO); + } + if( ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) { + ucBmpAC |= BIT(ACI_VI); + } + if( ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) { + ucBmpAC |= BIT(ACI_BE); + } + if( ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) { + ucBmpAC |= BIT(ACI_BK); + } + + prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC; + + prStaRec->ucUapsdSp = (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5; + + } + break; + + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + + break; + + case ELEM_ID_HT_CAP: + /* Some client won't put the WMM IE if client is 802.11n */ + if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) { + prStaRec->fgIsQoS = TRUE; + } + break; + default: + break; + } + } + + DBGLOG(QM, TRACE, ("MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS)); + + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmProcessAssocRsp ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + DEBUGFUNC("mqmProcessAssocRsp"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(prStaRec == NULL) { + return; + } + + prStaRec->fgIsQoS = FALSE; + + pucIEStart = pucIE; + + DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n", + prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS)); + + /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/ + //if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) + if((!prAdapter->rWifiVar.fgSupportQoS)) + { + return; + } + + /* Determine whether QoS is enabled with the association */ + else{ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){ + + switch(WMM_IE_OUI_SUBTYPE(pucIE)){ + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if(IE_LEN(pucIE) != 24){ + break; /* WMM Info IE with a wrong length */ + } + prStaRec->fgIsQoS = TRUE; + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if(IE_LEN(pucIE) != 7){ + break; /* WMM Info IE with a wrong length */ + } + prStaRec->fgIsQoS = TRUE; + break; + + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + break; + + case ELEM_ID_HT_CAP: + /* Some AP won't put the WMM IE if client is 802.11n */ + if ( IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) { + prStaRec->fgIsQoS = TRUE; + } + break; + default: + break; + } + } + + /* Parse AC parameters and write to HW CRs */ + if((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)){ + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE); + } + + DBGLOG(QM, TRACE, ("MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS)); + if(prStaRec->fgIsWmmSupported) { + nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex); + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmParseEdcaParameters ( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN PUINT_8 pucIE, + IN UINT_16 u2IELength, + IN BOOLEAN fgForceOverride + ) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("mqmParseEdcaParameters"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if(prStaRec == NULL) { + return; + } + + DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS)); + + if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)){ + return; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + + if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){ + + switch(WMM_IE_OUI_SUBTYPE(pucIE)){ + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if(IE_LEN(pucIE) != 24){ + break; /* WMM Param IE with a wrong length */ + } + else{ + P_AC_QUE_PARMS_T prAcQueParams; + P_IE_WMM_PARAM_T prIeWmmParam; + ENUM_WMM_ACI_T eAci; + PUINT_8 pucWmmParamSetCount; + //int i; + + pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount); + + prIeWmmParam = (P_IE_WMM_PARAM_T)pucIE; + + /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */ + if(!fgForceOverride){ + if(*pucWmmParamSetCount == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)){ + break; /* Ignore the IE without updating HW CRs */ + } + } + + /* Update Parameter Set Count */ + *pucWmmParamSetCount = (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT); + + /* Update EDCA parameters */ + for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){ + + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams); + + prAcQueParams->fgIsACMSet = + (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN; + + DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prAcQueParams->fgIsACMSet, + prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin, + prAcQueParams->u2CWmax, prAcQueParams->u2TxopLimit)); + } + } + break; + + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + break; + default: + break; + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE +* +* \param[in] prAdapter Adapter pointer +* \param[in] prIeWmmParam The pointer to the WMM Parameter IE +* \param[in] u4AcOffset The offset specifying the AC queue for parsing +* \param[in] prHwAcParams The parameter structure used to configure the HW CRs +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmFillAcQueParam( + IN P_IE_WMM_PARAM_T prIeWmmParam, + IN UINT_32 u4AcOffset, + OUT P_AC_QUE_PARMS_T prAcQueParams + ) +{ + prAcQueParams->u2Aifsn = *((PUINT_8)(&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4)); + + prAcQueParams->u2CWmax = + BIT(((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK) + >> WMM_ECW_WMAX_OFFSET)-1; + + prAcQueParams->u2CWmin = + BIT((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK)-1; + + WLAN_GET_FIELD_16(((PUINT_8)(&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)),&(prAcQueParams->u2TxopLimit)); + + prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME; + + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM/11n related IEs in scan results (only for AP peers) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prScanResult The scan result which shall be parsed to obtain needed info +* \param[out] prStaRec The obtained info is stored in the STA_REC +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmProcessScanResult( + IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prScanResult, + OUT P_STA_RECORD_T prStaRec + ) +{ + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + if (!prAdapter->rWifiVar.fgSupportQoS){ + return; + } + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + + /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){ + + switch(WMM_IE_OUI_SUBTYPE(pucIE)){ + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if(IE_LEN(pucIE) != 24){ + break; /* WMM Param IE with a wrong length */ + } + else{ + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_PARAM_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE); + } + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if(IE_LEN(pucIE) != 7){ + break; /* WMM Info IE with a wrong length */ + } + else{ + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_INFO_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE); + } + break; + + default: + /* A WMM QoS IE that doesn't matter. Ignore it. */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + DBGLOG(QM, LOUD, ("MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported)); + +} + +UINT_8 +qmGetStaRecIdx( + IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucEthDestAddr, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType + ) +{ + UINT_32 i; + P_STA_RECORD_T prTempStaRec; + + prTempStaRec = NULL; + + ASSERT(prAdapter); + + //4 <1> DA = BMCAST + if(IS_BMCAST_MAC_ADDR(pucEthDestAddr)){ + return STA_REC_INDEX_BMCAST; + } + + + //4 <2> Check if an AP STA is present + for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){ + prTempStaRec = &(prAdapter->arStaRec[i]); + if((prTempStaRec->ucNetTypeIndex == eNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)){ + return prTempStaRec->ucIndex; + } + } + + //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) + for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){ + prTempStaRec = &(prAdapter->arStaRec[i]); + if(prTempStaRec->fgIsValid){ + if(EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)){ + return prTempStaRec->ucIndex; + } + } + } + + + //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW + return STA_REC_INDEX_NOT_FOUND; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmGenerateWmmInfoIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_32 ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if(!prAdapter->rWifiVar.fgSupportQoS){ + return; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if(prStaRec == NULL) { + return; + } + + if(!prStaRec->fgIsWmmSupported) { + return; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prIeWmmInfo = (P_IE_WMM_INFO_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD intial queue configurations (delivery and trigger enabled)*/ +// if(prAdapter->rWifiVar.fgSupportUAPSD){ + if(prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported){ + + UINT_8 ucQosInfo = 0; + UINT_8 i; + + + /* Static U-APSD setting */ + for(i = ACI_BE; i <= ACI_VO; i++){ + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)){ + ucQosInfo |= (UINT_8)ucUapsd[i]; + } + } + + + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) { + switch (prPmProfSetupInfo->ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, INFO, ("MQM: Incorrect SP length \n")); + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + } + } + prIeWmmInfo->ucQosInfo = ucQosInfo; + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo); + +} + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief log2 calculation for CW +* +* @param[in] val value +* +* @return log2(val) +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 cwlog2(UINT_32 val) { + + UINT_32 n; + n=0; + + while (val >= 512) { n+= 9; val = val >> 9; } + while (val >= 16) { n+= 4; val >>= 4; } + while (val >= 2) { n+= 1; val >>= 1; } + return n; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Param IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmGenerateWmmParamIE ( + IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo + ) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD,("\n")); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if(!prAdapter->rWifiVar.fgSupportQoS){ + return; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if(prStaRec) { + if(!prStaRec->fgIsQoS) { + return; + } + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + + if(!prBssInfo->fgIsQBSS) { return; } + +#if 0 // 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. + if( prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && + prBssInfo->eCurrentOPMode != OP_MODE_BOW) + { + return; + } +#endif + + prIeWmmParam = (P_IE_WMM_PARAM_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD intial queue configurations (delivery and trigger enabled)*/ + if(prAdapter->rWifiVar.fgSupportUAPSD){ + + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + } + + /* EDCA parameter */ + + for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){ + + //DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + // eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , + // prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, + // prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, + // prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, + // prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); + + *( ((PUINT_8)(&prIeWmmParam->ucAciAifsn_BE)) + (eAci <<2) ) = (UINT_8) (aucACI[eAci] + | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM:0 ) + | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN))); +#if 1 + *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 + | (((prBssInfo->aucCWminLog2ForBcast[eAci] )) & WMM_ECW_WMIN_MASK) + | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci] )) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK) + ); +#else + *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 + | (cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmin + 1)) & WMM_ECW_WMIN_MASK) + | ((cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmax + 1)) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK) + ); +#endif + + WLAN_SET_FIELD_16( ((PUINT_8)(prIeWmmParam->aucTxopLimit_BE)) + (eAci<<2) + , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); + +} + + + + +ENUM_FRAME_ACTION_T +qmGetFrameAction( + IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, + IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType +) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + P_WLAN_MAC_HEADER_T prWlanFrame; + UINT_16 u2TxFrameCtrl; + + DEBUGFUNC("qmGetFrameAction"); + +#if (NIC_TX_BUFF_COUNT_TC4 > 2) +#define QM_MGMT_QUUEUD_THRESHOLD 2 +#else +#define QM_MGMT_QUUEUD_THRESHOLD 1 +#endif + + DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4)); + DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + /* XXX Check BOW P2P AIS time ot set active */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + if (eFrameType == FRAME_TYPE_MMPDU) { + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM + if ((u2TxFrameCtrl == MAC_FRAME_DEAUTH) && (prMsduInfo->pfTxDoneHandler == NULL)) { + return FRAME_ACTION_TX_PKT; + } + + } + + DBGLOG(QM, INFO, ("Drop packets Action (Inactive %u).\n",prBssInfo->ucNetTypeIndex)); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + return FRAME_ACTION_DROP_PKT; + } + + /* TODO Handle disconnect issue */ + + /* P2P probe Request frame */ + do { + if(eFrameType == FRAME_TYPE_MMPDU) { + ASSERT(prMsduInfo!=NULL); + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM + + if (u2TxFrameCtrl == MAC_FRAME_BEACON ) { + if( prBssInfo->fgIsNetAbsent) { + return FRAME_ACTION_DROP_PKT; + } + } + else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { + if( prBssInfo->fgIsNetAbsent) { + break; + } + } + else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) { + if( prBssInfo->fgIsNetAbsent) { + break; + } + DBGLOG(P2P, LOUD, ("Sending DEAUTH Frame\n")); + return FRAME_ACTION_TX_PKT; + } + /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */ + else if(u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_AUTH + || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ + || u2TxFrameCtrl == MAC_FRAME_ACTION) { + + if(prStaRec){ + if(prStaRec->fgIsInPS) { + if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) { + return FRAME_ACTION_TX_PKT; + } + else { + return FRAME_ACTION_QUEUE_PKT; + } + } + } + return FRAME_ACTION_TX_PKT; + } + + if (!prStaRec){ + return FRAME_ACTION_TX_PKT; + } + else { + if (!prStaRec->fgIsInUse) { + return FRAME_ACTION_DROP_PKT; + } + } + + } /* FRAME_TYPE_MMPDU */ + else if ((eFrameType == FRAME_TYPE_802_1X)){ + + if (!prStaRec){ + return FRAME_ACTION_TX_PKT; + } + else { + if (!prStaRec->fgIsInUse) { + return FRAME_ACTION_DROP_PKT; + } + if(prStaRec->fgIsInPS) { + if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) { + return FRAME_ACTION_TX_PKT; + } + else { + return FRAME_ACTION_QUEUE_PKT; + } + } + } + + } /* FRAME_TYPE_802_1X */ + else if ((!IS_BSS_ACTIVE(prBssInfo)) + || (!prStaRec) + || (!prStaRec->fgIsInUse)){ + return FRAME_ACTION_DROP_PKT; + } + }while(0); + + if (prBssInfo->fgIsNetAbsent){ + DBGLOG(QM, LOUD, ("Queue packets (Absent %u).\n",prBssInfo->ucNetTypeIndex)); + return FRAME_ACTION_QUEUE_PKT; + } + + if (prStaRec && prStaRec->fgIsInPS){ + DBGLOG(QM, LOUD, ("Queue packets (PS %u).\n",prStaRec->fgIsInPS)); + return FRAME_ACTION_QUEUE_PKT; + } + else { + switch (eFrameType){ + case FRAME_TYPE_802_1X: + if (!prStaRec->fgIsValid){ + return FRAME_ACTION_QUEUE_PKT; + } + break; + + case FRAME_TYPE_MMPDU: + break; + + default: + ASSERT(0); + } + } + + return FRAME_ACTION_TX_PKT; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle BSS change operation Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleEventBssAbsencePresence( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus; + P_BSS_INFO_T prBssInfo; + BOOLEAN fgIsNetAbsentOld; + + prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T)prEvent; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + //DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", + // prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); + + DBGLOG(QM, TRACE, ("NAF=%d,%d,%d\n", + prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); + + if(!prBssInfo->fgIsNetAbsent) { + QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_27); + } + else { + QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)){ + kalSetEvent(prAdapter->prGlueInfo); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle STA change PS mode Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleEventStaChangePsMode( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode; + P_STA_RECORD_T prStaRec; + BOOLEAN fgIsInPSOld; + + //DbgPrint("QM:Event -RxBa\n"); + + prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T)prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx); + ASSERT(prStaRec); + + if(prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs; + + qmUpdateFreeQuota( + prAdapter, + prStaRec, + prEventStaChangePsMode->ucUpdateMode, + prEventStaChangePsMode->ucFreeQuota); + + //DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", + // prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); + + + DBGLOG(QM, TRACE, ("PS=%d,%d\n", + prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)){ + kalSetEvent(prAdapter->prGlueInfo); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota Event from FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmHandleEventStaUpdateFreeQuota( + IN P_ADAPTER_T prAdapter, + IN P_WIFI_EVENT_T prEvent + ) +{ + P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota; + P_STA_RECORD_T prStaRec; + + + prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T)prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx); + ASSERT(prStaRec); + + if(prStaRec) { + if(prStaRec->fgIsInPS) { + qmUpdateFreeQuota( + prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); + + kalSetEvent(prAdapter->prGlueInfo); + } +#if 0 + DBGLOG(QM, TRACE, ("qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota)); +#endif + + DBGLOG(QM, TRACE, ("UFQ=%d,%d,%d\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota)); + + + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota +* +* \param[in] prStaRec the STA +* \param[in] ucUpdateMode the method to update free quota +* \param[in] ucFreeQuota the value for update +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmUpdateFreeQuota( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUpdateMode, + IN UINT_8 ucFreeQuota + ) +{ + + UINT_8 ucFreeQuotaForNonDelivery; + UINT_8 ucFreeQuotaForDelivery; + + ASSERT(prStaRec); + DBGLOG(QM, LOUD, ("qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n", + prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota )); + + if(!prStaRec->fgIsInPS)return; + + switch (ucUpdateMode) { + case FREE_QUOTA_UPDATE_MODE_INIT: + case FREE_QUOTA_UPDATE_MODE_OVERWRITE: + prStaRec->ucFreeQuota = ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_INCREASE: + prStaRec->ucFreeQuota += ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_DECREASE: + prStaRec->ucFreeQuota -= ucFreeQuota; + break; + default: + ASSERT(0); + } + + DBGLOG(QM, LOUD, ("qmUpdateFreeQuota new ucFreeQuota=%d)\n", + prStaRec->ucFreeQuota )); + + ucFreeQuota = prStaRec->ucFreeQuota; + + ucFreeQuotaForNonDelivery = 0; + ucFreeQuotaForDelivery = 0; + + if(ucFreeQuota > 0) { + if( prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD*/) { + /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */ + + if(prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota>>1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } + else if(prStaRec->ucFreeQuotaForNonDelivery == 0 && prStaRec->ucFreeQuotaForDelivery == 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota>>1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } + else if(prStaRec->ucFreeQuotaForNonDelivery > 0) { + /* NonDelivery is not busy */ + if(ucFreeQuota >= 3 ) { + ucFreeQuotaForNonDelivery = 2; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery ; + } + else { + ucFreeQuotaForDelivery = ucFreeQuota; + ucFreeQuotaForNonDelivery = 0; + } + } + else if(prStaRec->ucFreeQuotaForDelivery > 0) { + /* Delivery is not busy */ + if(ucFreeQuota >= 3 ) { + ucFreeQuotaForDelivery = 2; + ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery; + } + else { + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } + + } + else { + /* !prStaRec->fgIsUapsdSupported */ + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } /* ucFreeQuota > 0 */ + + prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery; + prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery; + + DBGLOG(QM, LOUD, ("new QuotaForDelivery = %d QuotaForNonDelivery = %d\n", + prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery )); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the reorder queued RX packets +* +* \param[in] (none) +* +* \return The number of queued RX packets +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +qmGetRxReorderQueuedBufferCount( + IN P_ADAPTER_T prAdapter + ) +{ + UINT_32 i, u4Total; + P_QUE_MGT_T prQM = &prAdapter->rQM; + u4Total = 0; + /* XXX The summation may impact the performance */ + for(i =0; iarRxBaTable[i].rReOrderQue.u4NumElem; +#if DBG && 0 + if(QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))){ + ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0); + } +#endif + } + ASSERT(u4Total <=( CFG_NUM_OF_QM_RX_PKT_NUM*2)); + return u4Total; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c new file mode 100755 index 000000000000..bdd30aa9ee72 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c @@ -0,0 +1,1369 @@ +/* +** $Id: @(#) gl_bow.c@@ +*/ + +/*! \file gl_bow.c + \brief Main routines of Linux driver interface for 802.11 PAL (BT 3.0 + HS) + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_bow.c $ + * + * 02 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00235223] [Rose][ICS][Cross Feature][AEE-IPANIC]The device reboot automatically and then the "KE" pops up after you turn on the "Airplane mode".(once) + * + * [Root Cause] + * PAL operates BOW char dev poll after BOW char dev is registered. + * + * [Solution] + * Rejects PAL char device operation after BOW is unregistered or when wlan GLUE_FLAG_HALT is set. + * + * This is a workaround for BOW driver robustness, happens only in ICS. + * + * Root cause should be fixed by CR [ALPS00231570] + * + * 02 03 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00118114] [Rose][ICS][Free Test][Bluetooth]The "KE" pops up after you turn on the airplane mode.(5/5) + * + * [Root Cause] + * PAL operates BOW char dev poll after BOW char dev is registered. + * + * [Solution] + * Rejects PAL char device operation after BOW is unregistered. + * + * Happens only in ICS. + * + * Notified PAL owener to reivew MTKBT/PAL closing BOW char dev procedure. + * + * [Side Effect] + * None. + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 25 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Modify ampc0 char device for major number 151 for all MT6575 projects. + * + * 07 28 2011 cp.wu + * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl + * unlocked_ioctl returns as long instead of int. + * + * 07 28 2011 cp.wu + * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl + * migrate to unlocked ioctl interface + * + * 04 12 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add WMM IE for BOW initiator data. + * + * 04 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * replace alloc_netdev to alloc_netdev_mq for BoW + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update net register and BOW for concurrent features. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information + * fill mac header length information for 802.1x frames. + * + * 11 11 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BoW timer assert issue. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 09 14 2010 cp.wu + * NULL + * correct typo: POLLOUT instead of POLL_OUT + * + * 09 13 2010 cp.wu + * NULL + * add waitq for poll() and read(). + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change variable names for multiple physical link to match with coding convention + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * multiple BoW interfaces need to compare with peer address + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * fix kalIndicateBOWEvent. + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_BOW_TEST + UINT_32 g_u4PrevSysTime = 0; + UINT_32 g_u4CurrentSysTime = 0; + UINT_32 g_arBowRevPalPacketTime[11]; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +// forward declarations +static ssize_t +mt6620_ampc_read( + IN struct file *filp, + IN char __user *buf, + IN size_t size, + IN OUT loff_t *ppos); + +static ssize_t +mt6620_ampc_write( + IN struct file *filp, + OUT const char __user *buf, + IN size_t size, + IN OUT loff_t *ppos); + +static long +mt6620_ampc_ioctl( + IN struct file *filp, + IN unsigned int cmd, + IN OUT unsigned long arg); + +static unsigned int +mt6620_ampc_poll( + IN struct file *filp, + IN poll_table *wait); + +static int +mt6620_ampc_open( + IN struct inode *inodep, + IN struct file *filp); + +static int +mt6620_ampc_release( + IN struct inode *inodep, + IN struct file *filp); + + +// character file operations +static const struct file_operations mt6620_ampc_fops = { + //.owner = THIS_MODULE, + .read = mt6620_ampc_read, + .write = mt6620_ampc_write, + .unlocked_ioctl = mt6620_ampc_ioctl, + .poll = mt6620_ampc_poll, + .open = mt6620_ampc_open, + .release = mt6620_ampc_release, +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for character device to communicate with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +glRegisterAmpc ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + if(prGlueInfo->rBowInfo.fgIsRegistered == TRUE) { + return FALSE; + } + else { +#if 0 + // 1. allocate major number dynamically + + if(alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), + 0, // first minor number + 1, // number + GLUE_BOW_DEVICE_NAME) !=0) + + return FALSE; +#endif + +#if 1 + +#if defined (CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if(register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, + 1, // number + GLUE_BOW_DEVICE_NAME) !=0) + + return FALSE; +#endif + + // 2. spin-lock initialization + // spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); + + // 3. initialize kfifo +/* prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + GFP_KERNEL, + &(prGlueInfo->rBowInfo.rSpinLock));*/ + if ((kfifo_alloc((struct kfifo *) &(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL))) + goto fail_kfifo_alloc; + +// if(prGlueInfo->rBowInfo.prKfifo == NULL) + if(&(prGlueInfo->rBowInfo.rKfifo) == NULL) + goto fail_kfifo_alloc; + + // 4. initialize cdev + cdev_init(&(prGlueInfo->rBowInfo.cdev), &mt6620_ampc_fops); + // prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; + prGlueInfo->rBowInfo.cdev.ops = &mt6620_ampc_fops; + + // 5. add character device + if(cdev_add(&(prGlueInfo->rBowInfo.cdev), + prGlueInfo->rBowInfo.u4DeviceNumber, + 1)) + goto fail_cdev_add; + + + // 6. in queue initialization + init_waitqueue_head(&(prGlueInfo->rBowInfo.outq)); + + // 7. finish + prGlueInfo->rBowInfo.fgIsRegistered = TRUE; + return TRUE; + +fail_cdev_add: + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +// kfifo_free(prGlueInfo->rBowInfo.prKfifo); +fail_kfifo_alloc: + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + return FALSE; + } +} /* end of glRegisterAmpc */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister character device for communicating with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +glUnregisterAmpc ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + if(prGlueInfo->rBowInfo.fgIsRegistered == FALSE) { + return FALSE; + } + else { + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + // 1. free netdev if necessary +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + // 2. removal of character device + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + // 3. free kfifo +// kfifo_free(prGlueInfo->rBowInfo.prKfifo); + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +// prGlueInfo->rBowInfo.prKfifo = NULL; +// prGlueInfo->rBowInfo.rKfifo = NULL; + + // 4. free device number + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; + } +} /* end of glUnregisterAmpc */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t +mt6620_ampc_read( + IN struct file *filp, + IN char __user *buf, + IN size_t size, + IN OUT loff_t *ppos) +{ + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + ssize_t retval; + + P_GLUE_INFO_T prGlueInfo; + prGlueInfo = (P_GLUE_INFO_T)(filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) { + return -EFAULT; + } + + // size check +// if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) + if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +// retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); + +// kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); +// kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) + retval = -EIO; + + if(copy_to_user(buf, aucBuffer, retval)) + retval = -EIO; + + return retval; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief write handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t +mt6620_ampc_write( + IN struct file *filp, + OUT const char __user *buf, + IN size_t size, + IN OUT loff_t *ppos) +{ +#if CFG_BOW_TEST + UINT_8 i; +#endif + + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + P_AMPC_COMMAND prCmd; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T)(filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) { + return -EFAULT; + } + + if(size > MAX_BUFFER_SIZE) + return -EINVAL; + else if(copy_from_user(aucBuffer, buf, size)) + return -EIO; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("AMP driver CMD buffer size : %d.\n", size)); + + for(i = 0; i < MAX_BUFFER_SIZE; i++) + { + DBGLOG(BOW, EVENT, ("AMP write content : 0x%x.\n", aucBuffer[i])); + } + + DBGLOG(BOW, EVENT, ("BoW CMD write.\n")); +#endif + + prCmd = (P_AMPC_COMMAND) aucBuffer; + + #if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength)); + + DBGLOG(BOW, EVENT, ("AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T))); + #endif + + // size check + if(prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) + { + #if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("Wrong CMD total length.\n")); + #endif + + return -EINVAL; + } + + if(wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS) + return size; + else + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static long +mt6620_ampc_ioctl( + IN struct file *filp, + IN unsigned int cmd, + IN OUT unsigned long arg) +{ + int err = 0; + P_GLUE_INFO_T prGlueInfo; + prGlueInfo = (P_GLUE_INFO_T)(filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) { + return -EFAULT; + } + + // permission check + if(_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + // no ioctl is implemented yet + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int +mt6620_ampc_poll( + IN struct file *filp, + IN poll_table *wait) +{ + unsigned int retval; + P_GLUE_INFO_T prGlueInfo; + prGlueInfo = (P_GLUE_INFO_T)(filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) { + return -EFAULT; + } + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); // always accepts incoming command packets + +// DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval)); + +// if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0) + if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0) + { + retval |= (POLLIN | POLLRDNORM); + +// DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval)); + + } + + return retval; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief open handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int +mt6620_ampc_open( + IN struct inode *inodep, + IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_BOW_INFO prBowInfo; + + prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev); + ASSERT(prBowInfo); + + prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo); + ASSERT(prGlueInfo); + + // set-up private data + filp->private_data = prGlueInfo; + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief close handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int +mt6620_ampc_release( + IN struct inode *inodep, + IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + prGlueInfo = (P_GLUE_INFO_T)(filp->private_data); + + ASSERT(prGlueInfo); + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBOWEvent( + IN P_GLUE_INFO_T prGlueInfo, + IN P_AMPC_EVENT prEvent + ) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + // check device + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) { + return; + } + +/* u4AvailSize = + GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo);*/ + + u4AvailSize = + GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + + u4EventSize = + prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T); + + // check kfifo availability + if(u4AvailSize < u4EventSize) { + DBGLOG(BOW, EVENT, ("[bow] no space for event: %d/%d\n", + u4EventSize, + u4AvailSize)); + return; + } + + // queue into kfifo +// kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); +// kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); + kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8)prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE +kalGetBowState ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 aucPeerAddress[6] + ) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalGetBowState.\n")); +#endif + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) + { + if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) + { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i])); + +#endif + + return prGlueInfo->rBowInfo.aeState[i]; + } + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalSetBowState ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BOW_DEVICE_STATE eBowState, + IN UINT_8 aucPeerAddress[6] + ) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalSetBowState.\n")); + + DBGLOG(BOW, EVENT, ("kalSetBowState, prGlueInfo->rBowInfo.arPeerAddr, %x:%x:%x:%x:%x:%x.\n", + prGlueInfo->rBowInfo.arPeerAddr[0], + prGlueInfo->rBowInfo.arPeerAddr[1], + prGlueInfo->rBowInfo.arPeerAddr[2], + prGlueInfo->rBowInfo.arPeerAddr[3], + prGlueInfo->rBowInfo.arPeerAddr[4], + prGlueInfo->rBowInfo.arPeerAddr[5])); + + DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); +#endif + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) + { + if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) + { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], + aucPeerAddress[4], + aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, ("kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i])); +#endif + + return TRUE; + } + } + + return FALSE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi global state +* +* \param[in] +* prGlueInfo +* +* \return +* BOW_DEVICE_STATE_DISCONNECTED +* in case there is no BoW connection or +* BoW connection under initialization +* +* BOW_DEVICE_STATE_STARTING +* in case there is no BoW connection but +* some BoW connection under initialization +* +* BOW_DEVICE_STATE_CONNECTED +* in case there is any BoW connection available +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE +kalGetBowGlobalState ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + + +//Henry, can reduce this logic to indentify state change + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) { + if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_CONNECTED) { + return BOW_DEVICE_STATE_CONNECTED; + } + } + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) { + if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_STARTING) { + return BOW_DEVICE_STATE_STARTING; + } + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetBowFreqInKHz( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rBowInfo.u4FreqInKHz; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: Responder +* 1: Initiator +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +kalGetBowRole( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr + ) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) { + if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) { + return prGlueInfo->rBowInfo.aucRole[i]; + } + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* ucRole +* 0: Responder +* 1: Initiator +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalSetBowRole( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRole, + IN PARAM_MAC_ADDRESS rPeerAddr + ) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 1); + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) { + if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) { + prGlueInfo->rBowInfo.aucRole[i] = ucRole; //Henry, 0 : Responder, 1 : Initiator + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get available Bluetooth-over-Wi-Fi physical link number +* +* \param[in] +* prGlueInfo +* \return +* UINT_32 +* how many physical links are aviailable +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +kalGetBowAvailablePhysicalLinkCount( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + UINT_8 i; + UINT_8 ucLinkCount = 0; + + ASSERT(prGlueInfo); + + for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) { + if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) { + ucLinkCount++; + } + } + +#if 0//CFG_BOW_TEST + DBGLOG(BOW, EVENT, ("kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount)); +#endif + + return ucLinkCount; +} + +#if CFG_BOW_SEPARATE_DATA_PATH + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int +bowOpen( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 2. carrier on & start TX queue */ + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int +bowStop( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); + + /* 2. turn of carrier */ + if(netif_carrier_ok(prDev)) { + netif_carrier_off(prDev); + } + + return 0; +}; + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is TX entry point of NET DEVICE. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prDev Pointer to struct net_device + * + * \retval NETDEV_TX_OK - on success. + * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + */ +/*----------------------------------------------------------------------------*/ +static int +bowHardStartXmit( + IN struct sk_buff *prSkb, + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + PUINT_8 aucLookAheadBuf = NULL; + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + aucLookAheadBuf = prSkb->data; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + + if (!(ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && + aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) || (prSkb->len > 1514)) + { + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, ("Invalid BOW packet, skip tx\n")); +#endif + + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, ("GLUE_FLAG_HALT skip tx\n")); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, ("Tx sk_buff->len: %d\n", prSkb->len)); + DBGLOG(BOW, TRACE, ("Tx sk_buff->data_len: %d\n", prSkb->data_len)); + DBGLOG(BOW, TRACE, ("Tx sk_buff->data:\n")); + + for(i = 0; i < prSkb->len; i++) + { + DBGLOG(BOW, TRACE, ("%4x", prSkb->data[i])); + + if((i+1)%16 ==0) + { + DBGLOG(BOW, TRACE, ("\n")); + } + } + + DBGLOG(BOW, TRACE, ("\n"); +#endif + +#if CFG_BOW_TEST +// g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick(); + + g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies); + + i = g_u4CurrentSysTime - g_u4PrevSysTime; + + if ( (i >> 10) > 0) + { + i = 10; + } + else + { + i = i >> 7; + } + + g_arBowRevPalPacketTime[i]++; + + g_u4PrevSysTime = g_u4CurrentSysTime; + +#endif + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + netif_stop_subqueue(prDev, u2QueueIdx); + } + } + else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} + + +// callbacks for netdevice +static const struct net_device_ops bow_netdev_ops = { + .ndo_open = bowOpen, + .ndo_stop = bowStop, + .ndo_start_xmit = bowHardStartXmit, +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief initialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* prDevName +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalInitBowDevice( + IN P_GLUE_INFO_T prGlueInfo, + IN const char *prDevName + ) +{ + P_ADAPTER_T prAdapter; + P_GL_HIF_INFO_T prHif; + PARAM_MAC_ADDRESS rMacAddr; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + if(prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { + prGlueInfo->rBowInfo.prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM); + + if (!prGlueInfo->rBowInfo.prDevHandler) { + return FALSE; + } + else { + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; + + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; // change to local administrated address + memcpy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + memcpy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN); + + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, &(prHif->func->dev)); +#endif + + register_netdev(prGlueInfo->rBowInfo.prDevHandler); + + /* 2. net device initialize */ + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* 3. finish */ + prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE; + } + } + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief uninitialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalUninitBowDevice( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + //ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + if(prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + + if(netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) { + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + } + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + + return TRUE; + + } + else { + return FALSE; + } +} + +#endif // CFG_BOW_SEPARATE_DATA_PATH +#endif // CFG_ENABLE_BT_OVER_WIFI + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c new file mode 100755 index 000000000000..18c61c057c2f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c @@ -0,0 +1,1600 @@ +/* +** $Id: @(#) gl_cfg80211.c@@ +*/ + +/*! \file gl_cfg80211.c + \brief Main routines for supporintg MT6620 cfg80211 control interface + + This file contains the support routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_cfg80211.c $ +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 11 23 2012 yuche.tsai +** [ALPS00398671] [Acer-Tablet] Remove Wi-Fi Direct completely +** Fix bug of WiFi may reboot under user load, when WiFi Direct is removed.. +** +** 08 29 2012 chinglan.wang +** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng] +** . + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_SUPPORT_WAPI + extern UINT_8 keyStructBuf[1024]; /* add/remove key shared buffer */ +#else + extern UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for change STA type between + * 1. Infrastructure Client (Non-AP STA) + * 2. Ad-Hoc IBSS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_change_iface ( + struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if(type == NL80211_IFTYPE_STATION) { + eOpMode = NET_TYPE_INFRA; + } + else if(type == NL80211_IFTYPE_ADHOC) { + eOpMode = NET_TYPE_IBSS; + } + else { + return -EINVAL; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, + sizeof(eOpMode), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set infrastructure mode error:%lx\n", rStatus)); + } + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding key + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_add_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + struct key_params *params + ) +{ + PARAM_KEY_T rKey; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rslt = -EINVAL; + UINT_32 u4BufLen = 0; + UINT_8 tmp1[8]; + UINT_8 tmp2[8]; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if(mac_addr) { + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && + (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + } + if (rKey.arBSSID[0] != 0xFF) { + rKey.u4KeyIndex |= BIT(31); + if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || + (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) + rKey.u4KeyIndex |= BIT(30); + } + } + else { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + //rKey.u4KeyIndex |= BIT(31); //Enable BIT 31 will make tx use bc key id, should use pairwise key id 0 + } + + if(params->key) { + //rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + if (params->key_len == 32) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((UINT_32)&(((P_P2P_PARAM_KEY_T)0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + &rKey, + rKey.u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_get_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*) + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for removing key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_del_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_32 u4BufLen = 0; + INT_32 i4Rslt = -EINVAL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if(mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + &rRemoveKey, + rRemoveKey.u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("remove key error:%lx\n", rStatus)); + } + else { + i4Rslt = 0; + } + + return i4Rslt; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting default key on an interface + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_set_default_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool unicast, + bool multicast + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ + +int +mtk_cfg80211_get_station ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4BufLen, u4Rate; + INT_32 i4Rssi; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBssid, + &arBssid[0], + sizeof(arBssid), + &u4BufLen); + + /* 1. check BSSID */ + if(UNEQUAL_MAC_ADDR(arBssid, mac)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, ("incorrect BSSID: ["MACSTR"] currently connected BSSID["MACSTR"]\n", + MAC2STR(mac), MAC2STR(arBssid))); + return -ENOENT; + } + + /* 2. fill TX rate */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, + &u4Rate, + sizeof(u4Rate), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("unable to retrieve link speed\n")); + } + else { + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + } + + if(prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, ("not yet connected\n")); + } + else { + /* 3. fill RSSI */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, + &i4Rssi, + sizeof(i4Rssi), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("unable to retrieve link speed\n")); + } + else { + sinfo->filled |= STATION_INFO_SIGNAL; + //in the cfg80211 layer, the signal is a signed char variable. + if(i4Rssi < -128) + sinfo->signal = -128; + else + sinfo->signal = i4Rssi; /* dBm */ + } + } + + sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets; + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets; + sinfo->filled |= STATION_INFO_TX_FAILED; + +#if 1 + { + WLAN_STATUS rStatus; + UINT_32 u4XmitError = 0; +// UINT_32 u4XmitOk = 0; +// UINT_32 u4RecvError = 0; +// UINT_32 u4RecvOk = 0; +// UINT_32 u4BufLen; + + /* @FIX ME: need a more clear way to do this */ + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryXmitError, + &u4XmitError, + sizeof(UINT_32), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); + + prGlueInfo->rNetDevStats.tx_errors = u4XmitError; + + } +#else + prGlueInfo->rNetDevStats.tx_errors = 0; +#endif + + sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors; + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to do a scan + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_scan ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_scan_request *request + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_SCAN_REQUEST_EXT_T rScanRequest; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T)); + + /* check if there is any pending scan not yet finished */ + if(prGlueInfo->prScanRequest != NULL) { + return -EBUSY; + } + + if(request->n_ssids == 0) { + rScanRequest.rSsid.u4SsidLen = 0; + } + else if(request->n_ssids == 1) { + COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, request->ssids[0].ssid_len); + } + else { + return -EINVAL; + } + + if(request->ie_len > 0) { + rScanRequest.u4IELength = request->ie_len; + rScanRequest.pucIE = (PUINT_8)(request->ie); + } + else { + rScanRequest.u4IELength = 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanExt, + &rScanRequest, + sizeof(PARAM_SCAN_REQUEST_EXT_T), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("scan error:%lx\n", rStatus)); + return -EINVAL; + } + + prGlueInfo->prScanRequest = request; + + return 0; +} + +static UINT_8 wepBuf[48]; + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to connect to + * the ESS with the specified parameters + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_connect ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + UINT_32 cipher; + PARAM_SSID_T rNewSsid; + BOOLEAN fgCarryWPSIE = FALSE; + ENUM_PARAM_OP_MODE_T eOpMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode > NET_TYPE_AUTO_SWITCH) + eOpMode = NET_TYPE_AUTO_SWITCH; + else + eOpMode = prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, + sizeof(eOpMode), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetInfrastructureMode fail 0x%lx\n", rStatus)); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA; + else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2; + else + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + + switch (sme->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY; + break; + default: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] = sme->crypto.ciphers_pairwise[0]; + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + break; + default: + DBGLOG(REQ, WARN, ("invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0])); + return -EINVAL; + } + } + + if (sme->crypto.cipher_group) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite = sme->crypto.cipher_group; + switch (sme->crypto.cipher_group) { + case WLAN_CIPHER_SUITE_WEP40: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; + break; + default: + DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n", + sme->crypto.cipher_group)); + return -EINVAL; + } + } + + if (sme->crypto.n_akm_suites) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] = sme->crypto.akm_suites[0]; + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + break; + default: + DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n", + sme->crypto.cipher_group)); + return -EINVAL; + } + } else if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA2; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + break; + default: + DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n", + sme->crypto.cipher_group)); + return -EINVAL; + } + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? + AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + + //prGlueInfo->prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + //prGlueInfo->prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0; + prGlueInfo->fgWpsActive = FALSE; + //prGlueInfo->prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0; + + if (sme->ie && sme->ie_len > 0) { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PUINT_8 prDesiredIE = NULL; + +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + sme->ie, + sme->ie_len, + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SEC, WARN, ("[wapi] set wapi assoc info error:%lx\n", rStatus)); + } +#endif +#if CFG_SUPPORT_WPS2 + if (wextSrchDesiredWPSIE(sme->ie, + sme->ie_len, + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + prGlueInfo->fgWpsActive = TRUE; + fgCarryWPSIE = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWSCAssocInfo, + prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SEC, WARN, ("WSC] set WSC assoc info error:%lx\n", rStatus)); + } + } +#endif + } + + /* clear WSC Assoc IE buffer in case WPS IE is not detected */ + if(fgCarryWPSIE == FALSE) { + kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200); + prGlueInfo->u2WSCAssocInfoIELen = 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set auth mode error:%lx\n", rStatus)); + } + + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) { + if (cipher & IW_AUTH_CIPHER_CCMP) { + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } + else if (cipher & IW_AUTH_CIPHER_TKIP) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + } + else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } + else if (cipher & IW_AUTH_CIPHER_NONE){ + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + } + else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(eEncStatus), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set encryption mode error:%lx\n", rStatus)); + } + + if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + kalMemSet(prWepKey, 0, sizeof(prWepKey)); + prWepKey->u4Length = 12 + sme->key_len; + prWepKey->u4KeyLength = (UINT_32) sme->key_len; + prWepKey->u4KeyIndex = (UINT_32) sme->key_idx; + prWepKey->u4KeyIndex |= BIT(31); + if (prWepKey->u4KeyLength > 32) { + DBGLOG(REQ, WARN, ("Too long key length (%u)\n", prWepKey->u4KeyLength)); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, + prWepKey->u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus)); + return -EFAULT; + } + } + + if(sme->ssid_len > 0) { + /* connect by SSID */ + COPY_SSID(rNewSsid.aucSsid, rNewSsid.u4SsidLen, sme->ssid, sme->ssid_len); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID) &rNewSsid, + sizeof(PARAM_SSID_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set SSID:%lx\n", rStatus)); + return -EINVAL; + } + } + else { + /* connect by BSSID */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssid, + (PVOID) sme->bssid, + sizeof(MAC_ADDR_LEN), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set BSSID:%lx\n", rStatus)); + return -EINVAL; + } + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to disconnect from + * currently connected ESS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_disconnect ( + struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDisassociate, + NULL, + 0, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("disassociate error:%lx\n", rStatus)); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to join an IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_join_ibss ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params + ) +{ + PARAM_SSID_T rNewSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* set channel */ + if(params->channel) { + u4ChnlFreq = nicChannelNum2Freq(params->channel->hw_value); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, + sizeof(u4ChnlFreq), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + } + + /* set SSID */ + kalMemCopy(rNewSsid.aucSsid, params->ssid, params->ssid_len); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID) &rNewSsid, + sizeof(PARAM_SSID_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set SSID:%lx\n", rStatus)); + return -EFAULT; + } + + return 0; + + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_leave_ibss ( + struct wiphy *wiphy, + struct net_device *ndev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDisassociate, + NULL, + 0, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("disassociate error:%lx\n", rStatus)); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_set_power_mgmt ( + struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, + int timeout + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_POWER_MODE ePowerMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if(enabled) { + if(timeout == -1) { + ePowerMode = Param_PowerModeFast_PSP; + } + else { + ePowerMode = Param_PowerModeMAX_PSP; + } + } + else { + ePowerMode = Param_PowerModeCAM; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, ("set_power_mgmt error:%lx\n", rStatus)); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_set_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_ADD\n")); + return -ENOMEM; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, pmksa->bssid, 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, pmksa->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("add pmkid error:%lx\n", rStatus)); + } + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to remove + * a cached PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_del_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa + ) +{ + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to flush + * all cached PMKID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_flush_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_FLUSH\n")); + return -ENOMEM; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("flush pmkid error:%lx\n", rStatus)); + } + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_remain_on_channel ( + struct wiphy *wiphy, + struct net_device *ndev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, + u64 *cookie + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_cancel_remain_on_channel ( + struct wiphy *wiphy, + struct net_device *ndev, + u64 cookie + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_mgmt_tx ( + struct wiphy *wiphy, + struct net_device *ndev, + struct ieee80211_channel *channel, + bool offscan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_mgmt_tx_cancel_wait ( + struct wiphy *wiphy, + struct net_device *ndev, + u64 cookie + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + + +#if CONFIG_NL80211_TESTMODE + +#if CFG_SUPPORT_WAPI +int +mtk_cfg80211_testmode_set_key_ext( + IN struct wiphy *wiphy, + IN void *data, + IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SET_KEY_EXTS prParams = (P_NL80211_DRIVER_SET_KEY_EXTS)NULL; + struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts *)NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4BufLen = 0; + + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + if(data && len) { + prParams = (P_NL80211_DRIVER_SET_KEY_EXTS)data; + } + + if(prParams) { + prIWEncExt = (struct iw_encode_exts *) &prParams->ext; + } + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->ucKeyID = prParams->key_index; + prWpiKey->ucKeyID --; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + //printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + //printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); + return -EINVAL; + } + + //printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } + else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } + +//#if CFG_SUPPORT_WAPI + //handle_sec_msg_final(prIWEncExt->key, 32, prIWEncExt->key, NULL); +//#endif + /* PN */ + memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE * 2); + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rstatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, + sizeof(PARAM_WPI_KEY_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + + +int +mtk_cfg80211_testmode_sw_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS)NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + if(data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS)data; + + if(prParams) { + if(prParams->set == 1){ + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC)wlanoidSetSwCtrlWrite, + &prParams->adr, + (UINT_32)8, + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + } + } + + if (WLAN_STATUS_SUCCESS != rstatus) { + fgIsValid = -EFAULT; + } + + return fgIsValid; +} + +int mtk_cfg80211_testmode_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS)NULL; + BOOLEAN fgIsValid = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + printk("--> %s()\n", __func__); +#endif + + if(data && len) + prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS)data; + + /* Clear the version byte */ + prParams->index = prParams->index & ~ BITS(24,31); + + if(prParams){ + switch(prParams->index){ + case 1: /* SW cmd */ + if(mtk_cfg80211_testmode_sw_cmd(wiphy, data, len)) + fgIsValid = TRUE; + break; + case 2: /* WAPI */ +#if CFG_SUPPORT_WAPI + if(mtk_cfg80211_testmode_set_key_ext(wiphy, data, len)) + fgIsValid = TRUE; +#endif + break; + default: + fgIsValid = TRUE; + break; + } + } + + return fgIsValid; +} +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c new file mode 100755 index 000000000000..30eee3dee1fe --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c @@ -0,0 +1,3144 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#7 $ +*/ + +/*! \file gl_init.c + \brief Main routines of Linux driver + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_init.c $ +** +** 11 15 2012 cp.wu +** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j +** do not try reconnecting when being disconnected by the peer + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 05 25 2012 yuche.tsai + * NULL + * Fix reset KE issue. + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 03 02 2012 terry.wu + * NULL + * EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 12 22 2011 george.huang + * [WCXRP00000905] [MT6628 Wi-Fi][FW] Code refinement for ROM/ RAM module dependency + * using global variable instead of stack for setting wlanoidSetNetworkAddress(), due to buffer may be released before TX thread handling + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 14 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Fix large network type index assert in FW issue. + * + * 11 14 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 06 2011 eddie.chen + * [WCXRP00001027] [MT6628 Wi-Fi][Firmware/Driver] Tx fragmentation + * Add rlmDomainGetChnlList symbol. + * + * 09 22 2011 cm.chang + * NULL + * Safer writng stype to avoid unitialized regitry structure + * + * 09 21 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Avoid possible structure alignment problem + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * expose scnQuerySparseChannel() for P2P-FSM. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 07 2011 wh.su + * [WCXRP00000839] [MT6620 Wi-Fi][Driver] Add the dumpMemory8 and dumpMemory32 EXPORT_SYMBOL + * Add the dumpMemory8 symbol export for debug mode. + * + * 07 06 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Improve BoW connection establishment speed. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Export one symbol for enhancement. + * + * 06 13 2011 eddie.chen + * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni + * Add tx rx statistics and netif_rx_ni. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 18 2011 cp.wu + * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain + * pass PHY_PARAM in NVRAM from driver to firmware. + * + * 05 09 2011 jeffrey.chang + * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change + * support ARP filter through kernel notifier + * + * 05 03 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Modify some driver connection flow or behavior to pass Sigma test more easier.. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 11 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * export wlan functions to p2p + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * glBusFreeIrq() should use the same pvCookie as glBusSetIrq() or request_irq()/free_irq() won't work as a pair. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 04 06 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port + * 2. update perm_addr as well for MAC address + * 3. not calling check_mem_region() anymore for eHPI + * 4. correct MSC_CS macro for 0-based notation + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * fix typo. + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 23 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * apply multi-queue operation only for linux kernel > 2.6.26 + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability for compatible with linux 2.6.12. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 18 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * remove early suspend functions + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * reverse order to prevent probing racing. + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similiar APIs to hide the difference. + * + * 03 15 2011 jeffrey.chang + * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM + * refine the queue_select function + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 10 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Remove unnecessary assert and message. + * + * 03 08 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Export nicQmUpdateWmmParms. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 02 24 2011 george.huang + * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames + * Support ARP filter during suspended + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 02 17 2011 terry.wu + * [WCXRP00000459] [MT6620 Wi-Fi][Driver] Fix deference null pointer problem in wlanRemove + * Fix deference a null pointer problem in wlanRemove. + * + * 02 16 2011 jeffrey.chang + * NULL + * fix compilig error + * + * 02 16 2011 jeffrey.chang + * NULL + * Add query ipv4 and ipv6 address during early suspend and late resume + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 02 11 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add one more export symbol. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 02 09 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Halt p2p module init and exit until TxThread finished p2p register and unregister. + * + * 02 08 2011 george.huang + * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler + * Support querying power mode OID. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue + * Export Deactivation Network. + * + * 02 01 2011 jeffrey.chang + * [WCXRP00000414] KAL Timer is not unregistered when driver not loaded + * Unregister the KAL timer during driver unloading + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 19 2011 cp.wu + * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 + * add compile option to check linux version 2.6.35 for different usage of system API to improve portability + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 15 2010 cp.wu + * [WCXRP00000265] [MT6620 Wi-Fi][Driver] Remove set_mac_address routine from legacy Wi-Fi Android driver + * remove set MAC address. MAC address is always loaded from NVRAM instead. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 21 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * . + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000106] [MT6620 Wi-Fi][Driver] Enable setting multicast callback in Android + * . + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 16 2010 yarco.yang + * NULL + * Support Linux x86 + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 jeffrey.chang + * NULL + * fix memory leak for module unloading + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 23 2010 jeffrey.chang + * + * bug fix: allocate regInfo when disabling firmware download + * + * 07 23 2010 jeffrey.chang + * + * use glue layer api to decrease or increase counter atomically + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power managment macro + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Query statistics from firmware + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * modify tcp/ip checksum offload flags + * + * 04 16 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix tcp/ip checksum offload bug + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set MAC address from firmware + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * are done in adapter layer. + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)improve none-glue code portability + * * (2) disable set Multicast address during atomic context + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding debug module + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix f/w download start and load address by using config.h + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download support + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\52 2009-10-27 22:49:59 GMT mtk01090 +** Fix compile error for Linux EHPI driver +** \main\maintrunk.MT5921\51 2009-10-20 17:38:22 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw. +** \main\maintrunk.MT5921\50 2009-10-08 10:33:11 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers. +** \main\maintrunk.MT5921\49 2009-09-28 20:19:05 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\48 2009-09-03 13:58:46 GMT mtk01088 +** remove non-used code +** \main\maintrunk.MT5921\47 2009-09-03 11:40:25 GMT mtk01088 +** adding the module parameter for wapi +** \main\maintrunk.MT5921\46 2009-08-18 22:56:41 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\45 2009-07-06 20:53:00 GMT mtk01088 +** adding the code to check the wapi 1x frame +** \main\maintrunk.MT5921\44 2009-06-23 23:18:55 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\43 2009-02-16 23:46:51 GMT mtk01461 +** Revise the order of increasing u4TxPendingFrameNum because of CFG_TX_RET_TX_CTRL_EARLY +** \main\maintrunk.MT5921\42 2009-01-22 13:11:59 GMT mtk01088 +** set the tid and 1x value at same packet reserved field +** \main\maintrunk.MT5921\41 2008-10-20 22:43:53 GMT mtk01104 +** Fix wrong variable name "prDev" in wlanStop() +** \main\maintrunk.MT5921\40 2008-10-16 15:37:10 GMT mtk01461 +** add handle WLAN_STATUS_SUCCESS in wlanHardStartXmit() for CFG_TX_RET_TX_CTRL_EARLY +** \main\maintrunk.MT5921\39 2008-09-25 15:56:21 GMT mtk01461 +** Update driver for Code review +** \main\maintrunk.MT5921\38 2008-09-05 17:25:07 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\37 2008-09-02 10:57:06 GMT mtk01461 +** Update driver for code review +** \main\maintrunk.MT5921\36 2008-08-05 01:53:28 GMT mtk01461 +** Add support for linux statistics +** \main\maintrunk.MT5921\35 2008-08-04 16:52:58 GMT mtk01461 +** Fix ASSERT if removing module in BG_SSID_SCAN state +** \main\maintrunk.MT5921\34 2008-06-13 22:52:24 GMT mtk01461 +** Revise status code handling in wlanHardStartXmit() for WLAN_STATUS_SUCCESS +** \main\maintrunk.MT5921\33 2008-05-30 18:56:53 GMT mtk01461 +** Not use wlanoidSetCurrentAddrForLinux() +** \main\maintrunk.MT5921\32 2008-05-30 14:39:40 GMT mtk01461 +** Remove WMM Assoc Flag +** \main\maintrunk.MT5921\31 2008-05-23 10:26:40 GMT mtk01084 +** modify wlanISR interface +** \main\maintrunk.MT5921\30 2008-05-03 18:52:36 GMT mtk01461 +** Fix Unset Broadcast filter when setMulticast +** \main\maintrunk.MT5921\29 2008-05-03 15:17:26 GMT mtk01461 +** Move Query Media Status to GLUE +** \main\maintrunk.MT5921\28 2008-04-24 22:48:21 GMT mtk01461 +** Revise set multicast function by using windows oid style for LP own back +** \main\maintrunk.MT5921\27 2008-04-24 12:00:08 GMT mtk01461 +** Fix multicast setting in Linux and add comment +** \main\maintrunk.MT5921\26 2008-03-28 10:40:22 GMT mtk01461 +** Fix set mac address func in Linux +** \main\maintrunk.MT5921\25 2008-03-26 15:37:26 GMT mtk01461 +** Add set MAC Address +** \main\maintrunk.MT5921\24 2008-03-26 14:24:53 GMT mtk01461 +** For Linux, set net_device has feature with checksum offload by default +** \main\maintrunk.MT5921\23 2008-03-11 14:50:52 GMT mtk01461 +** Fix typo +** \main\maintrunk.MT5921\22 2008-02-29 15:35:20 GMT mtk01088 +** add 1x decide code for sw port control +** \main\maintrunk.MT5921\21 2008-02-21 15:01:54 GMT mtk01461 +** Rearrange the set off place of GLUE spin lock in HardStartXmit +** \main\maintrunk.MT5921\20 2008-02-12 23:26:50 GMT mtk01461 +** Add debug option - Packet Order for Linux and add debug level - Event +** \main\maintrunk.MT5921\19 2007-12-11 00:11:12 GMT mtk01461 +** Fix SPIN_LOCK protection +** \main\maintrunk.MT5921\18 2007-11-30 17:02:25 GMT mtk01425 +** 1. Set Rx multicast packets mode before setting the address list +** \main\maintrunk.MT5921\17 2007-11-26 19:44:24 GMT mtk01461 +** Add OS_TIMESTAMP to packet +** \main\maintrunk.MT5921\16 2007-11-21 15:47:20 GMT mtk01088 +** fixed the unload module issue +** \main\maintrunk.MT5921\15 2007-11-07 18:37:38 GMT mtk01461 +** Fix compile warnning +** \main\maintrunk.MT5921\14 2007-11-02 01:03:19 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\13 2007-10-30 10:42:33 GMT mtk01425 +** 1. Refine for multicast list +** \main\maintrunk.MT5921\12 2007-10-25 18:08:13 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +** Revision 1.4 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:50 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//#define MAX_IOREQ_NUM 10 + +BOOLEAN fgIsUnderEarlierSuspend = false; + +struct semaphore g_halt_sem; +int g_u4HaltFlag = 0; + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +typedef struct _WLANDEV_INFO_T { + struct net_device *prDev; +} WLANDEV_INFO_T, *P_WLANDEV_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); +/* WCNCR 00002676, +keep OS wake up for 100ms after sdio interrupt happen, +make sure that RX & TX procedure isn't suspended +*/ +KAL_WAKE_LOCK_T isr_wakelock; + +#if 0 + MODULE_LICENSE("MTK Propietary"); +#else + MODULE_LICENSE("GPL"); +#endif + +#define NIC_INF_NAME "wlan%d" /* interface name */ + +#if DBG + UINT_8 aucDebugModule[DBG_MODULE_NUM]; + UINT_32 u4DebugModule = 0; +#endif /* DBG */ + +//4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 +static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = {{0}}; +static UINT_32 u4WlanDevNum = 0; /* How many NICs coexist now */ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_ENABLE_WIFI_DIRECT +static SUB_MODULE_HANDLER rSubModHandler[SUB_MODULE_NUM] = {{NULL}}; +#endif + +#define CHAN2G(_channel, _freq, _flags) \ + { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ + } +static struct ieee80211_channel mtk_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +#define CHAN5G(_channel, _flags) \ + { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ + } +static struct ieee80211_channel mtk_5ghz_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(169, 0), CHAN5G(173, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0) + +#define MT6620_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define MT6620_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = MT6620_MCS_INFO, \ +} + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = IEEE80211_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = MT6620_HT_CAP, +}; + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_5ghz = { + .band = IEEE80211_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = MT6620_HT_CAP, +}; + +static const UINT_32 mtk_cipher_suites[] = { + /* keep WEP first, it may be removed below */ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC +}; + +static struct cfg80211_ops mtk_wlan_ops = { + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .get_station = mtk_cfg80211_get_station, + .scan = mtk_cfg80211_scan, + .connect = mtk_cfg80211_connect, + .disconnect = mtk_cfg80211_disconnect, + .join_ibss = mtk_cfg80211_join_ibss, + .leave_ibss = mtk_cfg80211_leave_ibss, + .set_power_mgmt = mtk_cfg80211_set_power_mgmt, + .set_pmksa = mtk_cfg80211_set_pmksa, + .del_pmksa = mtk_cfg80211_del_pmksa, + .flush_pmksa = mtk_cfg80211_flush_pmksa, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, + .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, + #ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, + #endif +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if defined(CONFIG_HAS_EARLYSUSPEND) +extern int glRegisterEarlySuspend( + struct early_suspend *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend *prDesc); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Override the implementation of select queue +* +* \param[in] dev Pointer to struct net_device +* \param[in] skb Pointer to struct skb_buff +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +unsigned int _cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp = 0; + + /* skb->priority values from 256->263 are magic values + * directly indicate a specific 802.1d priority. This is + * to allow 802.1d priority to be passed directly in from + * tags + */ + + if (skb->priority >= 256 && skb->priority <= 263) { + return skb->priority - 256; + } + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + } + return dscp >> 5; +} + + +static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +static UINT_16 +wlanSelectQueue( + struct net_device *dev, + struct sk_buff *skb) +{ + skb->priority = _cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Load NVRAM data and translate it into REG_INFO_T +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* \param[out] prRegInfo Pointer to struct REG_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void +glLoadNvram ( + IN P_GLUE_INFO_T prGlueInfo, + OUT P_REG_INFO_T prRegInfo + ) +{ + UINT_32 i, j; + UINT_8 aucTmp[2]; + PUINT_8 pucDest; + + ASSERT(prGlueInfo); + ASSERT(prRegInfo); + + if((!prGlueInfo) || (!prRegInfo)) { + return; + } + + if(kalCfgDataRead16(prGlueInfo, + sizeof(WIFI_CFG_PARAM_STRUCT) - sizeof(UINT_16), + (PUINT_16)aucTmp) == TRUE) { + prGlueInfo->fgNvramAvailable = TRUE; + + // load MAC Address + for (i = 0 ; i < sizeof(PARAM_MAC_ADDR_LEN) ; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8)prRegInfo->aucMacAddr) + i)); + } + + // load country code + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucCountryCode[0]), + (PUINT_16)aucTmp); + + // cast to wide characters + prRegInfo->au2CountryCode[0] = (UINT_16) aucTmp[0]; + prRegInfo->au2CountryCode[1] = (UINT_16) aucTmp[1]; + + // load default normal TX power + for (i = 0 ; i < sizeof(TX_PWR_PARAM_T) ; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rTxPwr) + i, + (PUINT_16) (((PUINT_8)&(prRegInfo->rTxPwr)) + i)); + } + + // load feature flags + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucTxPwrValid), + (PUINT_16)aucTmp); + prRegInfo->ucTxPwrValid = aucTmp[0]; + prRegInfo->ucSupport5GBand = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2G4BwFixed20M), + (PUINT_16)aucTmp); + prRegInfo->uc2G4BwFixed20M = aucTmp[0]; + prRegInfo->uc5GBwFixed20M = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucEnable5GBand), + (PUINT_16)aucTmp); + prRegInfo->ucEnable5GBand = aucTmp[0]; + + /* load EFUSE overriding part */ + for (i = 0 ; i < sizeof(prRegInfo->aucEFUSE) ; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) + i, + (PUINT_16) (((PUINT_8)&(prRegInfo->aucEFUSE)) + i)); + } + + /* load band edge tx power control */ + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), + (PUINT_16)aucTmp); + prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN)aucTmp[0]; + if (aucTmp[0]) { + prRegInfo->cBandEdgeMaxPwrCCK = (INT_8)aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), + (PUINT_16)aucTmp); + prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8)aucTmp[0]; + prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8)aucTmp[1]; + } + + /* load regulation subbands */ + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), + (PUINT_16)aucTmp); + prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; + prRegInfo->ucRegChannelListIndex = aucTmp[1]; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + for (i = 0 ; i < MAX_SUBBAND_NUM; i++) { + pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i]; + for (j = 0; j < 6; j += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) + + (i * 6 + j), + (PUINT_16)aucTmp); + + *pucDest++ = aucTmp[0]; + *pucDest++ = aucTmp[1]; + } + } + } + } + else { + prGlueInfo->fgNvramAvailable = FALSE; + } + + return; +} + + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module init function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSubModRunInit( + P_GLUE_INFO_T prGlueInfo + ) +{ + /*now, we only have p2p module*/ + if(rSubModHandler[P2P_MODULE].fgIsInited == FALSE) { + rSubModHandler[P2P_MODULE].subModInit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = TRUE; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module exit function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSubModRunExit( + P_GLUE_INFO_T prGlueInfo + ) +{ + /*now, we only have p2p module*/ + if(rSubModHandler[P2P_MODULE].fgIsInited == TRUE) { + rSubModHandler[P2P_MODULE].subModExit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module init flag, force TxThread to run sub modle init +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanSubModInit( + P_GLUE_INFO_T prGlueInfo + ) +{ + //4 Mark HALT, notify main thread to finish current job + prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_INIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module INIT*/ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + +#if 0 + if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + p2pNetRegister(prGlueInfo); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module exit flag, force TxThread to run sub modle exit +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanSubModExit( + P_GLUE_INFO_T prGlueInfo + ) +{ +#if 0 + if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + p2pNetUnregister(prGlueInfo); + } +#endif + + //4 Mark HALT, notify main thread to finish current job + prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_EXIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module EXIT */ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set by sub module, indicate sub module is already inserted +* +* \param[in] rSubModInit, function pointer point to sub module init function +* \param[in] rSubModExit, function pointer point to sub module exit function +* \param[in] eSubModIdx, sub module index +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSubModRegisterInitExit( + SUB_MODULE_INIT rSubModInit, + SUB_MODULE_EXIT rSubModExit, + ENUM_SUB_MODULE_IDX_T eSubModIdx + ) +{ + rSubModHandler[eSubModIdx].subModInit = rSubModInit; + rSubModHandler[eSubModIdx].subModExit = rSubModExit; + rSubModHandler[eSubModIdx].fgIsInited = FALSE; +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief check wlan is launched or not +* +* \param[in] (none) +* +* \return TRUE, wlan is already started +* FALSE, wlan is not started yet +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wlanIsLaunched( + VOID + ) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + //4 <0> Sanity check + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (0 == u4WlanDevNum) { + return FALSE; + } + + prDev = arWlanDevInfo[u4WlanDevNum-1].prDev; + + ASSERT(prDev); + if (NULL == prDev) { + return FALSE; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (NULL == prGlueInfo) { + return FALSE; + } + + return prGlueInfo->prAdapter->fgIsWlanLaunched; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Export wlan GLUE_INFO_T pointer to p2p module +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return TRUE: get GlueInfo pointer successfully +* FALSE: wlan is not started yet +*/ +/*---------------------------------------------------------------------------*/ +BOOLEAN +wlanExportGlueInfo( + P_GLUE_INFO_T *prGlueInfoExpAddr + ) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (0 == u4WlanDevNum) { + return FALSE; + } + + prDev = arWlanDevInfo[u4WlanDevNum-1].prDev; + if (NULL == prDev) { + return FALSE; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (NULL == prGlueInfo) { + return FALSE; + } + + if(FALSE == prGlueInfo->prAdapter->fgIsWlanLaunched) { + return FALSE; + } + + *prGlueInfoExpAddr = prGlueInfo; + return TRUE; +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release prDev from wlandev_array and free tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void +wlanClearDevIdx ( + struct net_device *prDev + ) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + + return; +} /* end of wlanClearDevIdx() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate an unique interface index, net_device::ifindex member for this +* wlan device. Store the net_device in wlandev_array, and initialize +* tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \retval >= 0 The device number. +* \retval -1 Fail to get index. +*/ +/*----------------------------------------------------------------------------*/ +static int +wlanGetDevIdx ( + struct net_device *prDev + ) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *) NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, a primary SOCKET interface to configure +* the interface lively. Handle an ioctl call on one of our devices. +* Everything Linux ioctl specific is done here. Then we pass the contents +* of the ifr->data to the request message handler. +* +* \param[in] prDev Linux kernel netdevice +* +* \param[in] prIFReq Our private ioctl request structure, typed for the generic +* struct ifreq so we can use ptr to function +* +* \param[in] cmd Command ID +* +* \retval WLAN_STATUS_SUCCESS The IOCTL command is executed successfully. +* \retval OTHER The execution of IOCTL command is failed. +*/ +/*----------------------------------------------------------------------------*/ +int +wlanDoIOCTL( + struct net_device *prDev, + struct ifreq *prIFReq, + int i4Cmd + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIFReq); + if (!prDev || !prIFReq) { + DBGLOG(INIT, WARN, ("%s Invalid input data\n", __FUNCTION__)); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, WARN, ("%s No glue info\n", __FUNCTION__)); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + return -EINVAL; + } + + printk ("ioctl %x\n", i4Cmd); + + if (i4Cmd == SIOCGIWPRIV) { + /* 0x8B0D, get private ioctl table */ + ret = wext_get_priv(prDev, prIFReq); + } + else if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIFReq, i4Cmd); + } + else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIFReq, i4Cmd); + } + else { + DBGLOG(INIT, WARN, ("Unexpected ioctl command: 0x%04x\n", i4Cmd)); + /* return 0 for safe? */ + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to set multicast list and set rx mode. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +static struct delayed_work workq; +static struct net_device *gPrDev; + +static void +wlanSetMulticastList (struct net_device *prDev) +{ + gPrDev = prDev; + schedule_delayed_work(&workq, 0); +} + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this */ + +static void +wlanSetMulticastListWorkQueue (struct work_struct *work) { + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen; + struct net_device *prDev = gPrDev; + + down(&g_halt_sem); + if (g_u4HaltFlag) { + up(&g_halt_sem); + return; + } + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(INIT, WARN, ("abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", + prDev, prGlueInfo)); + up(&g_halt_sem); + return; + } + + if (prDev->flags & IFF_PROMISC) { + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + } + + if (prDev->flags & IFF_BROADCAST) { + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + } + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { +#else + (prDev->mc_count > MAX_NUM_GROUP_ADDR)) { +#endif + + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } + else { + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + up(&g_halt_sem); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + return; + } + + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + struct netdev_hw_addr *ha; +#else + struct dev_mc_list *prMcList; +#endif + PUINT_8 prMCAddrList = NULL; + UINT_32 i = 0; + + down(&g_halt_sem); + if (g_u4HaltFlag) { + up(&g_halt_sem); + return; + } + + prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + netdev_for_each_mc_addr(ha, prDev) { + if(i < MAX_NUM_GROUP_ADDR) { + memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); + i++; + } + } +#else + for (i = 0, prMcList = prDev->mc_list; + (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR); + i++, prMcList = prMcList->next) { + memcpy((prMCAddrList + i * ETH_ALEN), prMcList->dmi_addr, ETH_ALEN); + } +#endif + + up(&g_halt_sem); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, + prMCAddrList, + (i * ETH_ALEN), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + + return; +} /* end of wlanSetMulticastList() */ + + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this */ + +void +p2pSetMulticastListWorkQueueWrapper (P_GLUE_INFO_T prGlueInfo) { + + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + DBGLOG(INIT, WARN, ("abnormal dev or skb: prGlueInfo(0x%p)\n", + prGlueInfo)); + return; + } + +#if CFG_ENABLE_WIFI_DIRECT + if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + mtk_p2p_wext_set_Multicastlist(prGlueInfo); + } +#endif + + return; +} /* end of p2pSetMulticastListWorkQueueWrapper() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is TX entry point of NET DEVICE. +* +* \param[in] prSkb Pointer of the sk_buff to be sent +* \param[in] prDev Pointer to struct net_device +* +* \retval NETDEV_TX_OK - on success. +* \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. +*/ +/*----------------------------------------------------------------------------*/ +int +wlanHardStartXmit( + struct sk_buff *prSkb, + struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, ("GLUE_FLAG_HALT skip tx\n")); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, ("sk_buff->len: %d\n", prSkb->len)); + DBGLOG(BOW, TRACE, ("sk_buff->data_len: %d\n", prSkb->data_len)); + DBGLOG(BOW, TRACE, ("sk_buff->data:\n")); + + for(i = 0; i < prSkb->len; i++) + { + DBGLOG(BOW, TRACE, ("%4x", prSkb->data[i])); + + if((i+1)%16 ==0) + { + DBGLOG(BOW, TRACE, ("\n")); + } + } + + DBGLOG(BOW, TRACE, ("\n")); +#endif + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + #if CFG_DBG_GPIO_PINS + { + /* TX request from OS */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_HIGH); + } + #endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); +#endif + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + netif_stop_subqueue(prDev, u2QueueIdx); + } +#else + if (prGlueInfo->i4TxPendingFrameNum >= CFG_TX_STOP_NETIF_QUEUE_THRESHOLD) { + netif_stop_queue(prDev); + } +#endif + } else { + //printk("is security frame\n"); + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + DBGLOG(TX, EVENT, ("\n+++++ pending frame %d len = %d +++++\n", prGlueInfo->i4TxPendingFrameNum, prSkb->len)); + prGlueInfo->rNetDevStats.tx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.tx_packets++; + + //pr->u4Flag |= GLUE_FLAG_TXREQ; + //wake_up_interruptible(&prGlueInfo->waitq); + kalSetEvent(prGlueInfo); + + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} /* end of wlanHardStartXmit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] prDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +*/ +/*----------------------------------------------------------------------------*/ +struct net_device_stats * +wlanGetStats ( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + #if 0 + WLAN_STATUS rStatus; + UINT_32 u4XmitError = 0; + UINT_32 u4XmitOk = 0; + UINT_32 u4RecvError = 0; + UINT_32 u4RecvOk = 0; + UINT_32 u4BufLen; + + ASSERT(prDev); + + /* @FIX ME: need a more clear way to do this */ + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryXmitError, + &u4XmitError, + sizeof(UINT_32), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryXmitOk, + &u4XmitOk, + sizeof(UINT_32), + TRUE, + TRUE, + TRUE, + &u4BufLen); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRcvOk, + &u4RecvOk, + sizeof(UINT_32), + TRUE, + TRUE, + TRUE, + &u4BufLen); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRcvError, + &u4RecvError, + sizeof(UINT_32), + TRUE, + TRUE, + TRUE, + &u4BufLen); + prGlueInfo->rNetDevStats.rx_packets = u4RecvOk; + prGlueInfo->rNetDevStats.tx_packets = u4XmitOk; + prGlueInfo->rNetDevStats.tx_errors = u4XmitError; + prGlueInfo->rNetDevStats.rx_errors = u4RecvError; + //prGlueInfo->rNetDevStats.rx_bytes = rCustomNetDevStats.u4RxBytes; + //prGlueInfo->rNetDevStats.tx_bytes = rCustomNetDevStats.u4TxBytes; + //prGlueInfo->rNetDevStats.rx_errors = rCustomNetDevStats.u4RxErrors; + //prGlueInfo->rNetDevStats.multicast = rCustomNetDevStats.u4Multicast; + #endif + //prGlueInfo->rNetDevStats.rx_packets = 0; + //prGlueInfo->rNetDevStats.tx_packets = 0; + prGlueInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->rNetDevStats.rx_errors = 0; + //prGlueInfo->rNetDevStats.rx_bytes = 0; + //prGlueInfo->rNetDevStats.tx_bytes = 0; + prGlueInfo->rNetDevStats.rx_errors = 0; + prGlueInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->rNetDevStats; + +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int +wlanInit( + struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (!prDev) { + return -ENXIO; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12) + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); +#else + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue, NULL); +#endif + + return 0; /* success */ +} /* end of wlanInit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void +wlanUninit( + struct net_device *prDev + ) +{ + return; +} /* end of wlanUninit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->open +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanOpen succeeds. +* \retval < 0 The execution of wlanOpen failed. +*/ +/*----------------------------------------------------------------------------*/ +static int +wlanOpen( + struct net_device *prDev + ) +{ + ASSERT(prDev); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + netif_tx_start_all_queues(prDev); +#else + netif_start_queue(prDev); +#endif + + return 0; /* success */ +} /* end of wlanOpen() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->stop +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanStop succeeds. +* \retval < 0 The execution of wlanStop failed. +*/ +/*----------------------------------------------------------------------------*/ +static int +wlanStop( + struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if(prGlueInfo->prScanRequest != NULL) { + prScanRequest = prGlueInfo->prScanRequest; + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if(prScanRequest) { + cfg80211_scan_done(prScanRequest, TRUE); + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + netif_tx_stop_all_queues(prDev); +#else + netif_stop_queue(prDev); +#endif + + return 0; /* success */ +} /* end of wlanStop() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +VOID +wlanUpdateChannelTable( + P_GLUE_INFO_T prGlueInfo + ) +{ + UINT_8 i, j; + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; + + // 1. Disable all channel + for(i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + } + + for(i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + } + + // 2. Get current domain channel list + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, + aucChannelList); + + // 3. Enable specific channel based on domain channel list + for(i = 0; i < ucNumOfChannel; i++) { + switch(aucChannelList[i].eBand) { + case BAND_2G4: + for(j = 0 ; j < ARRAY_SIZE(mtk_2ghz_channels) ; j++) { + if(mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for(j = 0 ; j < ARRAY_SIZE(mtk_5ghz_channels) ; j++) { + if(mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + default: + break; + } + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register the device to the kernel and return the index. +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanNetRegister succeeds. +* \retval < 0 The execution of wlanNetRegister failed. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 +wlanNetRegister( + struct wireless_dev *prWdev + ) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4DevIdx = -1; + + ASSERT(prWdev); + + + do { + if (!prWdev) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + + if ((i4DevIdx = wlanGetDevIdx(prWdev->netdev)) < 0) { + DBGLOG(INIT, ERROR, ("wlanNetRegister: net_device number exceeds.\n")); + break; + } + + /* adjust channel support status */ + wlanUpdateChannelTable((P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy)); + + if (wiphy_register(prWdev->wiphy) < 0) { + DBGLOG(INIT, ERROR, ("wlanNetRegister: wiphy context is not registered.\n")); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } + + if(register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, ("wlanNetRegister: net_device context is not registered.\n")); + + wiphy_unregister(prWdev->wiphy); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } + + if(i4DevIdx != -1) { + prGlueInfo->fgIsRegistered = TRUE; + } + } + while(FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister the device from the kernel +* +* \param[in] prWdev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +wlanNetUnregister( + struct wireless_dev *prWdev + ) +{ + P_GLUE_INFO_T prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, ("wlanNetUnregister: The device context is NULL\n")); + return; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + + wlanClearDevIdx(prWdev->netdev); + unregister_netdev(prWdev->netdev); + wiphy_unregister(prWdev->wiphy); + + prGlueInfo->fgIsRegistered = FALSE; + + DBGLOG(INIT, INFO, ("unregister wireless_dev(0x%p)\n", prWdev)); + + return; +} /* end of wlanNetUnregister() */ + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + .ndo_set_rx_mode = wlanSetMulticastList, +#else + .ndo_set_multicast_list = wlanSetMulticastList, +#endif + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method for creating Linux NET4 struct net_device object and the +* private data(prGlueInfo and prAdapter). Setup the IO address to the HIF. +* Assign the function pointer to the net_device object +* +* \param[in] pvData Memory address for the device +* +* \retval Not null The wireless_dev object. +* \retval NULL Fail to create wireless_dev object +*/ +/*----------------------------------------------------------------------------*/ +static struct lock_class_key rSpinKey[SPIN_LOCK_NUM]; +static struct wireless_dev * +wlanNetCreate( + PVOID pvData + ) +{ + struct wireless_dev *prWdev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 i; + struct device *prDev; + + //4 <1.1> Create wireless_dev + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + DBGLOG(INIT, INFO, ("wireless_dev prWdev(0x%p) allocated\n", prWdev)); + if (!prWdev) { + DBGLOG(INIT, ERROR, ("Allocating memory to wireless_dev context failed\n")); + return NULL; + } + + //4 <1.2> Create wiphy + prWdev->wiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); + DBGLOG(INIT, INFO, ("wiphy (0x%p) allocated\n", prWdev->wiphy)); + if (!prWdev->wiphy) { + DBGLOG(INIT, ERROR, ("Allocating memory to wiphy device failed\n")); + kfree(prWdev); + return NULL; + } + + //4 <1.3> co-relate wiphy & prDev +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *)pvData), &prDev); +#else + prDev = ((struct sdio_func *) pvData)->dev; +#endif + if (!prDev) { + printk(KERN_ALERT DRV_NAME "unable to get struct dev for wlan\n"); + } + set_wiphy_dev(prWdev->wiphy, prDev); + + //4 <1.4> configure wireless_dev & wiphy + prWdev->iftype = NL80211_IFTYPE_STATION; + prWdev->wiphy->max_scan_ssids = 1; /* FIXME: for combo scan */ + prWdev->wiphy->max_scan_ie_len = 512; + prWdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + prWdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz; + prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + prWdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWdev->wiphy->cipher_suites = (const u32 *)mtk_cipher_suites; + prWdev->wiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + prWdev->wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_SUPPORTS_FW_ROAM; + #else + prWdev->wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY; + #endif + + //4 <2> Create Glue structure + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, ("Allocating memory to glue layer failed\n")); + goto netcreate_err; + } + + //4 <3> Initial Glue structure + //4 <3.1> create net device + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, ether_setup, CFG_MAX_TXQ_NUM); + + DBGLOG(INIT, INFO, ("net_device prDev(0x%p) allocated\n", prGlueInfo->prDevHandler)); + if (!prGlueInfo->prDevHandler) { + DBGLOG(INIT, ERROR, ("Allocating memory to net_device context failed\n")); + goto netcreate_err; + } + + //4 <3.1.1> initialize net device varaiables + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; + + prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prGlueInfo->prDevHandler->wireless_handlers = &wext_handler_def; +#endif + netif_carrier_off(prGlueInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + //4 <3.1.2> co-relate with wiphy bi-directionally + prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prGlueInfo->prDevHandler->features = NETIF_F_HW_CSUM; +#endif + prWdev->netdev = prGlueInfo->prDevHandler; + + //4 <3.1.3> co-relate net device & prDev + SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy)); + + //4 <3.2> initiali glue variables + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->ePowerState = ParamDeviceStateD0; + prGlueInfo->fgIsMacAddrOverride = FALSE; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); +#if CFG_ENABLE_WIFI_DIRECT + init_completion(&prGlueInfo->rSubModComp); +#endif + + /* initialize timer for OID timeout checker */ + kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler); + + for (i = 0; i < SPIN_LOCK_NUM; i++) { + spin_lock_init(&prGlueInfo->rSpinLock[i]); + lockdep_set_class(&prGlueInfo->rSpinLock[i], &rSpinKey[i]); + } + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + + /* initialize semaphore for ioctl */ + sema_init(&g_halt_sem, 1); + g_u4HaltFlag = 0; + + //4 <4> Create Adapter structure + prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); + + if (!prAdapter) { + DBGLOG(INIT, ERROR, ("Allocating memory to adapter failed\n")); + goto netcreate_err; + } + + prGlueInfo->prAdapter = prAdapter; + +#ifdef CONFIG_CFG80211_WEXT + //4 <5> Use wireless extension to replace IOCTL + prWdev->wiphy->wext = &wext_handler_def; +#endif + + goto netcreate_done; + +netcreate_err: + if (NULL != prAdapter) { + wlanAdapterDestroy(prAdapter); + prAdapter = NULL; + } + + if (NULL != prGlueInfo->prDevHandler) { + free_netdev(prGlueInfo->prDevHandler); + prGlueInfo->prDevHandler = NULL; + } + + if (NULL != prWdev->wiphy) { + wiphy_free(prWdev->wiphy); + prWdev->wiphy = NULL; + } + + if (NULL != prWdev) { + /* Free net_device and private data, which are allocated by + * alloc_netdev(). + */ + kfree(prWdev); + prWdev = NULL; + } + +netcreate_done: + + return prWdev; +} /* end of wlanNetCreate() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroying the struct net_device object and the private data. +* +* \param[in] prWdev Pointer to struct wireless_dev. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +wlanNetDestroy( + struct wireless_dev *prWdev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prWdev); + + if (!prWdev) { + DBGLOG(INIT, ERROR, ("wlanNetDestroy: The device context is NULL\n")); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + + /* destroy kal OS timer */ + kalCancelTimer(prGlueInfo); + + glClearHifInfo(prGlueInfo); + + wlanAdapterDestroy(prGlueInfo->prAdapter); + prGlueInfo->prAdapter = NULL; + + /* Free net_device and private data, which are allocated by alloc_netdev(). + */ + free_netdev(prWdev->netdev); + wiphy_free(prWdev->wiphy); + + kfree(prWdev); + + return; +} /* end of wlanNetDestroy() */ + +#ifndef CONFIG_X86 +UINT_8 g_aucBufIpAddr[32] = {0}; + +static void wlanEarlySuspend(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + + DBGLOG(INIT, INFO, ("*********wlanEarlySuspend************\n")); + + // <1> Sanity check and acquire the net_device + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if(u4WlanDevNum == 0){ + DBGLOG(INIT, ERROR, ("wlanEarlySuspend u4WlanDevNum==0 invalid!!\n")); + return; + } + prDev = arWlanDevInfo[u4WlanDevNum-1].prDev; + ASSERT(prDev); + +fgIsUnderEarlierSuspend = true; + + // <2> get the IPv4 address + if(!prDev || !(prDev->ip_ptr)||\ + !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ + DBGLOG(INIT, INFO, ("ip is not avaliable.\n")); + return; + } + + // <3> acquire the prGlueInfo + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + // <4> copy the IPv4 address + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + DBGLOG(INIT, INFO, ("ip is %d.%d.%d.%d\n", + ip[0],ip[1],ip[2],ip[3])); + + // todo: traverse between list to find whole sets of IPv4 addresses + if (!((ip[0] == 0) && + (ip[1] == 0) && + (ip[2] == 0) && + (ip[3] == 0))) { + u4NumIPv4++; + } + +#ifdef CONFIG_IPV6 + // <5> get the IPv6 address + if(!prDev || !(prDev->ip6_ptr)||\ + !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ + DBGLOG(INIT, INFO, ("ipv6 is not avaliable.\n")); + return; + } + // <6> copy the IPv6 address + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0],ip6[1],ip6[2],ip6[3], + ip6[4],ip6[5],ip6[6],ip6[7], + ip6[8],ip6[9],ip6[10],ip6[11], + ip6[12],ip6[13],ip6[14],ip6[15] + )); + + // todo: traverse between list to find whole sets of IPv6 addresses + if (!((ip6[0] == 0) && + (ip6[1] == 0) && + (ip6[2] == 0) && + (ip6[3] == 0) && + (ip6[4] == 0) && + (ip6[5] == 0))) { + //u4NumIPv6++; + } + +#endif + + // <7> set up the ARP filter + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +// UINT_8 aucBuf[32] = {0}; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); +#endif + } +#ifdef CONFIG_IPV6 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID)prParamNetAddrList, + u4Len, + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus)); + } + } +} + +static void wlanLateResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack +#endif + + DBGLOG(INIT, INFO, ("*********wlanLateResume************\n")); + + // <1> Sanity check and acquire the net_device + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if(u4WlanDevNum == 0){ + DBGLOG(INIT, ERROR, ("wlanLateResume u4WlanDevNum==0 invalid!!\n")); + return; + } + prDev = arWlanDevInfo[u4WlanDevNum-1].prDev; + ASSERT(prDev); + +fgIsUnderEarlierSuspend = false; + + // <2> get the IPv4 address + if(!prDev || !(prDev->ip_ptr)||\ + !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ + DBGLOG(INIT, INFO, ("ip is not avaliable.\n")); + return; + } + + // <3> acquire the prGlueInfo + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + // <4> copy the IPv4 address + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + DBGLOG(INIT, INFO, ("ip is %d.%d.%d.%d\n", + ip[0],ip[1],ip[2],ip[3])); + +#ifdef CONFIG_IPV6 + // <5> get the IPv6 address + if(!prDev || !(prDev->ip6_ptr)||\ + !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ + DBGLOG(INIT, INFO, ("ipv6 is not avaliable.\n")); + return; + } + // <6> copy the IPv6 address + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0],ip6[1],ip6[2],ip6[3], + ip6[4],ip6[5],ip6[6],ip6[7], + ip6[8],ip6[9],ip6[10],ip6[11], + ip6[12],ip6[13],ip6[14],ip6[15] + )); +#endif + // <7> clear the ARP filter + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +// UINT_8 aucBuf[32] = {0}; + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID)prParamNetAddrList, + u4Len, + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus)); + } + } +} + +#if defined(CONFIG_HAS_EARLYSUSPEND) +static struct early_suspend mt6620_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void wlan_early_suspend(struct early_suspend *h) +{ + DBGLOG(INIT, INFO, ("*********wlan_early_suspend************\n")); + wlanEarlySuspend(); +} + +static void wlan_late_resume(struct early_suspend *h) +{ + DBGLOG(INIT, INFO, ("*********wlan_late_resume************\n")); + wlanLateResume(); +} +#endif //defined(CONFIG_HAS_EARLYSUSPEND) +#endif //! CONFIG_X86 + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Wlan probe function. This function probes and initializes the device. +* +* \param[in] pvData data passed by bus driver init function +* _HIF_EHPI: NULL +* _HIF_SDIO: sdio bus driver handle +* +* \retval 0 Success +* \retval negative value Failed +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 +wlanProbe( + PVOID pvData + ) +{ + struct wireless_dev *prWdev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + INT_32 i4DevIdx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4Status = 0; + BOOL bRet = FALSE; + + + do { +#if DBG + int i; + /* Initialize DEBUG CLASS of each module */ + for (i = 0; i < DBG_MODULE_NUM; i++) { + aucDebugModule[i] = DBG_CLASS_ERROR | \ + DBG_CLASS_WARN | \ + DBG_CLASS_STATE | \ + DBG_CLASS_TRACE | \ + DBG_CLASS_EVENT; + //aucDebugModule[i] = 0; + } +#if 0 + aucDebugModule[DBG_INIT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_ARB_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_JOIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + //aucDebugModule[DBG_RX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_TX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_NIC_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_HAL_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_KEVIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO | DBG_CLASS_TEMP; + aucDebugModule[DBG_SCAN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_REQ_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + //aucDebugModule[DBG_MGT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; + aucDebugModule[DBG_RSN_IDX] |= DBG_CLASS_TRACE; + aucDebugModule[DBG_ROAMING_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO; +#endif +#endif /* DBG */ + + //4 <1> Initialize the IO port of the interface + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + + bRet = glBusInit(pvData); + + /* Cannot get IO address from interface */ + if (FALSE == bRet) { + DBGLOG(INIT, ERROR, (KERN_ALERT "wlanProbe: glBusInit() fail\n")); + i4Status = -EIO; + break; + } + + //4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) + if ((prWdev = wlanNetCreate(pvData)) == NULL) { + DBGLOG(INIT, ERROR, ("wlanProbe: No memory for dev and its private\n")); + i4Status = -ENOMEM; + break; + } + + //4 <2.5> Set the ioaddr to HIF Info + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + gPrDev = prGlueInfo->prDevHandler; + glSetHifInfo(prGlueInfo, (UINT_32) pvData); + + + /* main thread is created in this function */ + init_waitqueue_head(&prGlueInfo->waitq); + // + + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + + + + //prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); + + //4 <4> Setup IRQ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + //i4Status = glBusSetIrq(prWdev->netdev, NULL, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, ("wlanProbe: Set IRQ error\n")); + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->u4CSUMFlags = (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP); +#endif + + //4 <5> Start Device + // +#if CFG_ENABLE_FW_DOWNLOAD + /* before start adapter, we need to open and load firmware */ + { + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); + kalMemSet(prRegInfo, 0, sizeof(REG_INFO_T)); + prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS; + prRegInfo->u4LoadAddress = CFG_FW_LOAD_ADDRESS; + + // Load NVRAM content to REG_INFO_T + glLoadNvram(prGlueInfo, prRegInfo); + + //kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T)); + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + prRegInfo->fgEnArpFilter = TRUE; + + if (kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize) == NULL) { + i4Status = -EIO; + goto bailout; + } else { + if (wlanAdapterStart(prAdapter, prRegInfo, prFwBuffer, u4FwSize) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + } + } + + kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer); + +bailout: + //kfree(prRegInfo); + + if (i4Status < 0) { + break; + } + } +#else + //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); + kalMemSet(&prGlueInfo->rRegInfo, 0, sizeof(REG_INFO_T)); + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + // Load NVRAM content to REG_INFO_T + glLoadNvram(prGlueInfo, prRegInfo); + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + + if (wlanAdapterStart(prAdapter, prRegInfo, NULL, 0) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + break; + } +#endif + if(TRUE == prAdapter->fgEnable5GBand) + prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + + prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); + + /* set MAC address */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct sockaddr MacAddr; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCurrentAddr, + &MacAddr.sa_data, + PARAM_MAC_ADDR_LEN, + TRUE, + TRUE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, ("set MAC addr fail 0x%lx\n", rStatus)); + prGlueInfo->u4ReadyFlag = 0; + } else { + memcpy(prGlueInfo->prDevHandler->dev_addr, &MacAddr.sa_data, ETH_ALEN); + memcpy(prGlueInfo->prDevHandler->perm_addr, prGlueInfo->prDevHandler->dev_addr, ETH_ALEN); + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, ("MAC address: "MACSTR, MAC2STR(&MacAddr.sa_data))); +#endif + } + } + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID)&u4CSUMFlags, + sizeof(UINT_32), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, ("set HW checksum offload fail 0x%lx\n", rStatus)); + } + } +#endif + + //4 <3> Register the card + if ((i4DevIdx = wlanNetRegister(prWdev)) < 0){ + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, ("wlanProbe: Cannot register the net_device context to the kernel\n")); + break; + } + + glRegisterEarlySuspend(&mt6620_early_suspend_desc, wlan_early_suspend, wlan_late_resume); + wlanRegisterNotifier(); + + + //4 <6> Initialize /proc filesystem +#ifdef WLAN_INCLUDE_PROC + if ( (i4Status = procInitProcfs(prDev, NIC_DEVICE_ID_LOW)) < 0) { + DBGLOG(INIT, ERROR, ("wlanProbe: init procfs failed\n")); + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*wlan is launched*/ + prGlueInfo->prAdapter->fgIsWlanLaunched = TRUE; + /*if p2p module is inserted, notify tx_thread to init p2p network*/ + if(rSubModHandler[P2P_MODULE].subModInit) { + wlanSubModInit(prGlueInfo); + } +#endif + } + while (FALSE); + + return i4Status; +} /* end of wlanProbe() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method to stop driver operation and release all resources. Following +* this call, no frame should go up or down through this interface. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +wlanRemove( + VOID + ) +{ + struct net_device *prDev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + DBGLOG(INIT, INFO, ("Remove wlan!\n")); + + + //4 <0> Sanity check + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (0 == u4WlanDevNum) { + DBGLOG(INIT, INFO, ("0 == u4WlanDevNum\n")); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum-1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum-1]; + + ASSERT(prDev); + if (NULL == prDev) { + DBGLOG(INIT, INFO, ("NULL == prDev\n")); + return; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (NULL == prGlueInfo) { + DBGLOG(INIT, INFO, ("NULL == prGlueInfo\n")); + free_netdev(prDev); + return; + } + + +#if CFG_ENABLE_WIFI_DIRECT + prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE; + if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + p2pNetUnregister(prGlueInfo, FALSE); + p2pRemove(prGlueInfo); + } + +#if 0 + prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE; + //if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + if (prGlueInfo->prP2PInfo) { + //p2pRemove(prGlueInfo); + if (prGlueInfo->prP2PInfo->prDevHandler) { + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + prGlueInfo->prP2PInfo->prDevHandler = NULL; + + } + + + if(!p2PFreeInfo(prGlueInfo)) { + printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n"); + ASSERT(0); + return; + } + } +#endif +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if(prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /*wait 300ms for BoW module to send deauth*/ + kalMsleep(300); + } +#endif + + //4 <1> Stopping handling interrupt and free IRQ + glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev))); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + flush_delayed_work_sync(&workq); + + down(&g_halt_sem); + g_u4HaltFlag = 1; + + //4 <2> Mark HALT, notify main thread to stop, and clean up queued requests + prGlueInfo->u4Flag |= GLUE_FLAG_HALT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + + DBGLOG(INIT, INFO, ("mtk_sdiod stopped\n")); + + //prGlueInfo->rHifInfo.main_thread = NULL; + prGlueInfo->main_thread = NULL; + +#if CFG_ENABLE_BT_OVER_WIFI + if(prGlueInfo->rBowInfo.fgIsRegistered) { + glUnregisterAmpc(prGlueInfo); + } +#endif + + + //4 <3> Remove /proc filesystem. +#ifdef WLAN_INCLUDE_PROC + procRemoveProcfs(prDev, NIC_DEVICE_ID_LOW); +#endif /* WLAN_INCLUDE_PROC */ + + //4 <4> wlanAdapterStop + prAdapter = prGlueInfo->prAdapter; + + wlanAdapterStop(prAdapter); + DBGLOG(INIT, INFO, ("Number of Stalled Packets = %ld\n", prGlueInfo->i4TxPendingFrameNum)); + + //4 <5> Release the Bus + glBusRelease(prDev); + + up(&g_halt_sem); + + //4 <6> Unregister the card + wlanNetUnregister(prDev->ieee80211_ptr); + + //4 <7> Destroy the device + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + + glUnregisterEarlySuspend(&mt6620_early_suspend_desc); + wlanUnregisterNotifier(); + + return; +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +//1 Module Entry Point +static int __init initWlan(void) +{ + int ret = 0; + + DBGLOG(INIT, INFO, ("initWlan\n")); + + /* memory pre-allocation */ + kalInitIOBuffer(); + + //return ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO); + ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } + +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(); +#endif + + /*WCNCR00002676, keep OS wake up for 100ms*/ + KAL_WAKE_LOCK_INIT(NULL, &isr_wakelock, "WLAN TIME 2"); + return ret; +} /* end of initWlan() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +//1 Module Leave Point +static VOID __exit exitWlan(void) +{ + //printk("remove %p\n", wlanRemove); +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + + glUnregisterBus(wlanRemove); + + /*WCNCR00002676*/ + KAL_WAKE_LOCK_DESTROY(NULL, &isr_wakelock); + /* free pre-allocated memory */ + kalUninitIOBuffer(); + + DBGLOG(INIT, INFO, ("exitWlan\n")); + + return; +} /* end of exitWlan() */ + +module_init(initWlan); +module_exit(exitWlan); +#if 0 +/* export necessary symbol for p2p driver using */ +#if CFG_ENABLE_WIFI_DIRECT +EXPORT_SYMBOL(wlanSubModRegisterInitExit); +EXPORT_SYMBOL(wlanSubModExit); +EXPORT_SYMBOL(wlanSubModInit); + +EXPORT_SYMBOL(nicPmIndicateBssCreated); +EXPORT_SYMBOL(rlmProcessAssocRsp); +EXPORT_SYMBOL(kalSetEvent); +EXPORT_SYMBOL(rlmBssInitForAPandIbss); +EXPORT_SYMBOL(kalEnqueueCommand); +EXPORT_SYMBOL(nicIncreaseTxSeqNum); +EXPORT_SYMBOL(nicCmdEventQueryAddress); +EXPORT_SYMBOL(bssCreateStaRecFromBssDesc); +EXPORT_SYMBOL(rlmBssAborted); +EXPORT_SYMBOL(cnmStaRecResetStatus); +EXPORT_SYMBOL(mqmProcessAssocRsp); +EXPORT_SYMBOL(nicTxReturnMsduInfo); +EXPORT_SYMBOL(nicTxEnqueueMsdu); +EXPORT_SYMBOL(wlanProcessSecurityFrame); +EXPORT_SYMBOL(nicChannelNum2Freq); +EXPORT_SYMBOL(nicUpdateBss); +EXPORT_SYMBOL(wlanSendSetQueryCmd); +EXPORT_SYMBOL(cnmStaRecAlloc); +EXPORT_SYMBOL(cnmTimerInitTimer); +EXPORT_SYMBOL(rateGetRateSetFromIEs); +EXPORT_SYMBOL(nicOidCmdTimeoutCommon); +EXPORT_SYMBOL(cnmStaRecChangeState); +EXPORT_SYMBOL(rateGetDataRatesFromRateSet); +EXPORT_SYMBOL(cnmMgtPktAlloc); +EXPORT_SYMBOL(cnmMgtPktFree); +EXPORT_SYMBOL(wextSrchDesiredWPAIE); +EXPORT_SYMBOL(nicRxReturnRFB); +EXPORT_SYMBOL(cnmTimerStartTimer); +EXPORT_SYMBOL(cmdBufAllocateCmdInfo); +EXPORT_SYMBOL(cnmGetStaRecByAddress); +EXPORT_SYMBOL(nicMediaStateChange); +EXPORT_SYMBOL(bssUpdateBeaconContent); +EXPORT_SYMBOL(kalIoctl); +EXPORT_SYMBOL(nicActivateNetwork); +EXPORT_SYMBOL(nicDeactivateNetwork); +EXPORT_SYMBOL(kalRandomNumber); +EXPORT_SYMBOL(nicCmdEventSetCommon); +EXPORT_SYMBOL(cnmTimerStopTimer); +EXPORT_SYMBOL(nicIncreaseCmdSeqNum); +EXPORT_SYMBOL(authSendDeauthFrame); +EXPORT_SYMBOL(cnmMemAlloc); +EXPORT_SYMBOL(nicPmIndicateBssAbort); +EXPORT_SYMBOL(nicCmdEventSetIpAddress); +EXPORT_SYMBOL(mboxSendMsg); +EXPORT_SYMBOL(scanSearchBssDescByBssid); +EXPORT_SYMBOL(bssRemoveStaRecFromClientList); +EXPORT_SYMBOL(assocProcessRxDisassocFrame); +EXPORT_SYMBOL(authProcessRxDeauthFrame); +EXPORT_SYMBOL(cnmStaRecFree); +EXPORT_SYMBOL(rNonHTPhyAttributes); +EXPORT_SYMBOL(rNonHTApModeAttributes); +EXPORT_SYMBOL(cnmMemFree); +EXPORT_SYMBOL(wlanExportGlueInfo); +EXPORT_SYMBOL(bssInitForAP); +EXPORT_SYMBOL(nicPmIndicateBssConnected); +EXPORT_SYMBOL(rlmRspGenerateHtOpIE); +EXPORT_SYMBOL(bssGenerateExtSuppRate_IE); +EXPORT_SYMBOL(rlmRspGenerateErpIE); +EXPORT_SYMBOL(rlmRspGenerateHtCapIE); +EXPORT_SYMBOL(cnmGetStaRecByIndex); +EXPORT_SYMBOL(rsnGenerateWpaNoneIE); +EXPORT_SYMBOL(rlmRspGenerateExtCapIE); +EXPORT_SYMBOL(rsnGenerateRSNIE); +EXPORT_SYMBOL(rsnParseRsnIE); +#if CFG_SUPPORT_WPS +EXPORT_SYMBOL(wextSrchDesiredWPSIE); +#endif +EXPORT_SYMBOL(mboxDummy); +EXPORT_SYMBOL(saaFsmRunEventStart); +EXPORT_SYMBOL(saaFsmRunEventAbort); +EXPORT_SYMBOL(cnmP2PIsPermitted); +EXPORT_SYMBOL(cnmBss40mBwPermitted); +EXPORT_SYMBOL(mqmGenerateWmmParamIE); +EXPORT_SYMBOL(cnmPreferredChannel); +EXPORT_SYMBOL(bssAddStaRecToClientList); +EXPORT_SYMBOL(nicQmUpdateWmmParms); +EXPORT_SYMBOL(qmFreeAllByNetType); +EXPORT_SYMBOL(wlanQueryInformation); +EXPORT_SYMBOL(nicConfigPowerSaveProfile); +EXPORT_SYMBOL(scanSearchExistingBssDesc); +EXPORT_SYMBOL(scanAllocateBssDesc); +EXPORT_SYMBOL(wlanProcessCommandQueue); +EXPORT_SYMBOL(wlanAcquirePowerControl); +EXPORT_SYMBOL(wlanReleasePowerControl); +EXPORT_SYMBOL(wlanReleasePendingCMDbyNetwork); +#if DBG +EXPORT_SYMBOL(aucDebugModule); +EXPORT_SYMBOL(fgIsBusAccessFailed); +EXPORT_SYMBOL(allocatedMemSize); +EXPORT_SYMBOL(dumpMemory8); +EXPORT_SYMBOL(dumpMemory32); +#endif +EXPORT_SYMBOL(rlmDomainIsLegalChannel); +EXPORT_SYMBOL(scnQuerySparseChannel); +EXPORT_SYMBOL(rlmDomainGetChnlList); +EXPORT_SYMBOL(p2pSetMulticastListWorkQueueWrapper); +EXPORT_SYMBOL(nicUpdateRSSI); +EXPORT_SYMBOL(nicCmdEventQueryLinkQuality); +EXPORT_SYMBOL(kalGetMediaStateIndicated); +EXPORT_SYMBOL(nicFreq2ChannelNum); +EXPORT_SYMBOL(assocSendDisAssocFrame); +EXPORT_SYMBOL(nicUpdateBeaconIETemplate); +EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem); +EXPORT_SYMBOL(kalClearMgmtFramesByNetType); +EXPORT_SYMBOL(kalClearSecurityFramesByNetType); +EXPORT_SYMBOL(nicFreePendingTxMsduInfoByNetwork); +EXPORT_SYMBOL(bssComposeBeaconProbeRespFrameHeaderAndFF); +EXPORT_SYMBOL(bssBuildBeaconProbeRespFrameCommonIEs); +EXPORT_SYMBOL(wlanoidSetWapiAssocInfo); +EXPORT_SYMBOL(wlanoidSetWSCAssocInfo); +#endif +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c new file mode 100755 index 000000000000..0063f510a1c5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c @@ -0,0 +1,3982 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_kal.c#3 $ +*/ + +/*! \file gl_kal.c + \brief GLUE Layer will export the required procedures here for internal driver stack. + + This file contains all routines which are exported from GLUE Layer to internal + driver stack. +*/ + + + +/* +** $Log: gl_kal.c $ +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 05 31 2012 terry.wu + * NULL + * . + * + * 03 26 2012 cp.wu + * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist + * invoke put_cred() after get_current_cred() calls. + * + * 03 07 2012 yuche.tsai + * NULL + * Fix compile error when WiFi Direct is off. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 02 20 2012 cp.wu + * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist + * do not need to invoke free() while firmware image file doesn't exist + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 21 2011 cp.wu + * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing + * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer + * add more checking for such cases + * + * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. + * add some tweaking to protect such cases because that net device has become invalid. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 16 2011 yuche.tsai + * NULL + * Avoid using work thread. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 23 2011 yuche.tsai + * [WCXRP00000998] [Volunteer Patch][WiFi Direct][FW] P2P Social Channel & country domain issue + * Regulation domain feature check in. + * + * 08 12 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 13 2011 eddie.chen + * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni + * Add tx rx statistics and netif_rx_ni. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * correct i4TxPendingFrameNum decreasing. + * + * 03 23 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * apply multi-queue operation only for linux kernel > 2.6.26 + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability for compatible with linux 2.6.12. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * refix ... + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * correct compiling warning/error. + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * add more robust fault tolerance design when pre-allocation failed. (rarely happen) + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similiar APIs to hide the difference. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 14 2011 jeffrey.chang + * [WCXRP00000546] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] fix kernel build warning message + * fix kernel build warning message + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 19 2011 cp.wu + * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 + * add compile option to check linux version 2.6.35 for different usage of system API to improve portability + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not availble then warning message is shown + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 11 02 2010 jeffrey.chang + * [WCXRP00000145] [MT6620 Wi-Fi][Driver] fix issue of byte endian in packet classifier which discards BoW packets + * . + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 jeffrey.chang + * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform + * Remove redundant code which cause mismatch of power control release + * + * 10 25 2010 jeffrey.chang + * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform + * Remove redundant GLUE_HALT condfition to avoid unmatched release of power control + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue + * refine the scan ioctl to prevent hanging of Android UI + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 06 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * if there is NVRAM, then use MAC address on NVRAM as default MAC address. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 08 20 2010 yuche.tsai + * NULL + * Support second interface indicate when enabling P2P. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 16 2010 jeffrey.chang + * NULL + * remove redundant code which cause kernel panic + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 jeffrey.chang + * + * add new KAL api + * + * 07 23 2010 jeffrey.chang + * + * bug fix: allocate regInfo when disabling firmware download + * + * 07 23 2010 jeffrey.chang + * + * use glue layer api to decrease or increase counter atomically + * + * 07 22 2010 jeffrey.chang + * + * modify tx thread and remove some spinlock + * + * 07 22 2010 jeffrey.chang + * + * use different spin lock for security frame + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * add spinlock for pending security frame count + * + * 07 19 2010 jeffrey.chang + * + * adjust the timer unit to microsecond + * + * 07 19 2010 jeffrey.chang + * + * timer should return value greater than zero + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 19 2010 jeffrey.chang + * + * add new kal api + * + * 07 19 2010 jeffrey.chang + * + * for linux driver migration + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove unused files. + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix private ioctl for rftest + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * workaround for fixing request_firmware() failure on android 2.1 + * + * 05 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix kernel panic when debug mode enabled + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power managment macro + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Disable network interface after disassociation + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 15 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * change firmware name + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * flush pending TX packets while unloading driver + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set driver own before handling cmd queue + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used + * 2) fix ioctl + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add spinlock for i4TxPendingFrameNum access + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * * 2) add KAPI for handling association info + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding firmware download KAPI + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set MAC address from firmware + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. free cmdinfo after command is emiited. + * 2. for BoW frames, user priority is extracted from sk_buff directly. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)deliver the kalOidComplete status to upper layer + * (2) fix spin lock + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * * 2) add 2 kal API for later integration + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * raising the priority of processing interrupt + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Bug fix: the tx thread will cause starvation of MMC thread, and the interrupt will never come in + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding secondary command queue for improving non-glue code portability + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download kal api + * + * 03 25 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add Bluetooth-over-Wifi frame header check + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\50 2009-09-28 20:19:08 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\49 2009-08-18 22:56:44 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\48 2009-06-23 23:18:58 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\47 2008-11-19 11:55:43 GMT mtk01088 +** fixed some lint warning, and rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\46 2008-09-02 21:07:42 GMT mtk01461 +** Remove ASSERT(pvBuf) in kalIndicateStatusAndComplete(), this parameter can be NULL +** \main\maintrunk.MT5921\45 2008-08-29 16:03:21 GMT mtk01088 +** remove non-used code for code review, add assert check +** \main\maintrunk.MT5921\44 2008-08-21 00:32:49 GMT mtk01461 +** \main\maintrunk.MT5921\43 2008-05-30 20:27:02 GMT mtk01461 +** Rename KAL function +** \main\maintrunk.MT5921\42 2008-05-30 15:47:29 GMT mtk01461 +** \main\maintrunk.MT5921\41 2008-05-30 15:13:04 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\40 2008-05-29 14:15:14 GMT mtk01084 +** remove un-used KAL function +** \main\maintrunk.MT5921\39 2008-05-03 15:17:30 GMT mtk01461 +** Move Query Media Status to GLUE +** \main\maintrunk.MT5921\38 2008-04-24 11:59:44 GMT mtk01461 +** change awake queue threshold and remove code which mark #if 0 +** \main\maintrunk.MT5921\37 2008-04-17 23:06:35 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\36 2008-04-08 15:38:56 GMT mtk01084 +** add KAL function to setting pattern search function enable/ disable +** \main\maintrunk.MT5921\35 2008-04-01 23:53:13 GMT mtk01461 +** Add comment +** \main\maintrunk.MT5921\34 2008-03-26 15:36:48 GMT mtk01461 +** Add update MAC Address for Linux +** \main\maintrunk.MT5921\33 2008-03-18 11:49:34 GMT mtk01084 +** update function for initial value access +** \main\maintrunk.MT5921\32 2008-03-18 10:25:22 GMT mtk01088 +** use kal update associate request at linux +** \main\maintrunk.MT5921\31 2008-03-06 23:43:08 GMT mtk01385 +** 1. add Query Registry Mac address function. +** \main\maintrunk.MT5921\30 2008-02-26 09:47:57 GMT mtk01084 +** modify KAL set network address/ checksum offload part +** \main\maintrunk.MT5921\29 2008-02-12 23:26:53 GMT mtk01461 +** Add debug option - Packet Order for Linux +** \main\maintrunk.MT5921\28 2008-01-09 17:54:43 GMT mtk01084 +** modify the argument of kalQueryPacketInfo() +** \main\maintrunk.MT5921\27 2007-12-24 16:02:03 GMT mtk01425 +** 1. Revise csum offload +** \main\maintrunk.MT5921\26 2007-11-30 17:03:36 GMT mtk01425 +** 1. Fix bugs +** +** \main\maintrunk.MT5921\25 2007-11-29 01:57:17 GMT mtk01461 +** Fix Windows RX multiple packet retain problem +** \main\maintrunk.MT5921\24 2007-11-20 11:24:07 GMT mtk01088 +** CR90, not doing the netif_carrier_off to let supplicant 1x pkt can be rcv at hardstattXmit +** \main\maintrunk.MT5921\23 2007-11-09 16:36:44 GMT mtk01425 +** 1. Modify for CSUM offloading with Tx Fragment +** \main\maintrunk.MT5921\22 2007-11-07 18:37:39 GMT mtk01461 +** Add Tx Fragmentation Support +** \main\maintrunk.MT5921\21 2007-11-06 19:34:06 GMT mtk01088 +** add the WPS code, indicate the mgmt frame to upper layer +** \main\maintrunk.MT5921\20 2007-11-02 01:03:21 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\19 2007-10-30 11:59:38 GMT MTK01425 +** 1. Update wlanQueryInformation +** \main\maintrunk.MT5921\18 2007-10-30 10:44:57 GMT mtk01425 +** 1. Refine multicast list code +** 2. Refine TCP/IP csum offload code +** +** Revision 1.5 2007/07/17 13:01:18 MTK01088 +** add associate req and rsp function +** +** Revision 1.4 2007/07/13 05:19:19 MTK01084 +** provide timer set functions +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "gl_wext.h" +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if DBG +int allocatedMemSize = 0; +#endif + +extern struct semaphore g_halt_sem; +extern int g_u4HaltFlag; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PVOID pvIoBuffer = NULL; +static UINT_32 pvIoBufferSize = 0; +static UINT_32 pvIoBufferUsage = 0; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT +typedef enum _ENUM_WMTHWVER_TYPE_T{ + WMTHWVER_MT6620_E1 = 0x0, + WMTHWVER_MT6620_E2 = 0x1, + WMTHWVER_MT6620_E3 = 0x2, + WMTHWVER_MT6620_E4 = 0x3, + WMTHWVER_MT6620_E5 = 0x4, + WMTHWVER_MT6620_E6 = 0x5, + WMTHWVER_MT6620_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +extern ENUM_WMTHWVER_TYPE_T +mtk_wcn_wmt_hwver_get( + VOID + ); +#elif defined(MT5931) && CFG_MULTI_ECOVER_SUPPORT +typedef enum _ENUM_HWVER_TYPE_T{ + HWVER_MT5931_E1 = 0x1, + HWVER_MT5931_E2 = 0x2, + HWVER_MT5931_E3 = 0x3, + HWVER_MT5931_MAX, + HWVER_INVALID = 0xff +} ENUM_HWVER_TYPE_T, *P_ENUM_HWVER_TYPE_T; +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if CFG_ENABLE_FW_DOWNLOAD + +static struct file *filp = NULL; +static uid_t orgfsuid; +static gid_t orgfsgid; +static mm_segment_t orgfs; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* open firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalFirmwareOpen ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + /* FIX ME: since we don't have hotplug script in the filesystem + * , so the request_firmware() KAPI can not work properly + */ + + /* save uid and gid used for filesystem access. + * set user and group to 0(root) */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid = current->fsgid = 0; +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + struct cred *cred = (struct cred *) get_current_cred(); + orgfsuid = cred->fsuid; + orgfsgid = cred->fsgid; + cred->fsuid = cred->fsgid = 0; +#else + struct cred *cred = get_task_cred(current); + orgfsuid = cred->fsuid; + orgfsgid = cred->fsgid; + cred->fsuid = cred->fsgid = 0; +#endif + + ASSERT(prGlueInfo); + + + orgfs = get_fs(); + set_fs(get_ds()); + + + /* open the fw file */ +#if defined(MT6620) & CFG_MULTI_ECOVER_SUPPORT + switch(mtk_wcn_wmt_hwver_get()) { + case WMTHWVER_MT6620_E1: + case WMTHWVER_MT6620_E2: + case WMTHWVER_MT6620_E3: + case WMTHWVER_MT6620_E4: + case WMTHWVER_MT6620_E5: + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME, O_RDONLY, 0); + break; + + case WMTHWVER_MT6620_E6: + default: + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_E6", O_RDONLY, 0); + break; + } +#elif defined(MT5931) && CFG_MULTI_ECOVER_SUPPORT + switch (wlanGetEcoVersion(prGlueInfo->prAdapter)) { + case HWVER_MT5931_E1: + case HWVER_MT5931_E2: + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_E2", O_RDONLY, 0); + break; + case HWVER_MT5931_E3: + default: + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME, O_RDONLY, 0); + break; + } +#elif defined(MT6628) + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6628", O_RDONLY, 0); +#else + filp = filp_open("/etc/firmware/"CFG_FW_FILENAME, O_RDONLY, 0); +#endif + if (IS_ERR(filp)) { + DBGLOG(INIT, INFO, ("Open FW image: %s failed\n", CFG_FW_FILENAME)); + goto error_open; + } + DBGLOG(INIT, INFO, ("Open FW image: %s done\n", CFG_FW_FILENAME)); + return WLAN_STATUS_SUCCESS; + +error_open: + /* restore */ + set_fs(orgfs); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; +#else + cred->fsuid = orgfsuid; + cred->fsgid = orgfsgid; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + put_cred(cred); + #endif +#endif + return WLAN_STATUS_FAILURE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* release firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalFirmwareClose ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + if ((filp != NULL) && !IS_ERR(filp)) { + /* close firmware file */ + filp_close(filp, NULL); + + /* restore */ + set_fs(orgfs); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; +#else + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + struct cred *cred = (struct cred *) get_current_cred(); +#else + struct cred *cred = get_task_cred(current); +#endif + cred->fsuid = orgfsuid; + cred->fsgid = orgfsgid; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + put_cred(cred); + #endif + } +#endif + filp = NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* load firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalFirmwareLoad ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID prBuf, + IN UINT_32 u4Offset, + OUT PUINT_32 pu4Size + ) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + //l = filp->f_path.dentry->d_inode->i_size; + + /* the object must have a read method */ + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) || (filp->f_op->read == NULL)) { + goto error_read; + } else { + filp->f_pos = u4Offset; + *pu4Size = filp->f_op->read(filp, prBuf, *pu4Size, &filp->f_pos); + } + + return WLAN_STATUS_SUCCESS; + +error_read: + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* query firmware image size in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +kalFirmwareSize ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_32 pu4Size + ) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12) + *pu4Size = filp->f_path.dentry->d_inode->i_size; +#else + *pu4Size = filp->f_dentry->d_inode->i_size; +#endif + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to load firmware image +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image +* \param pu4FileLength File length and memory mapped length as well + +* \retval Map File Handle, used for unammping +*/ +/*----------------------------------------------------------------------------*/ + +PVOID +kalFirmwareImageMapping ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PPVOID ppvMapFileBuf, + OUT PUINT_32 pu4FileLength + ) +{ + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + do { + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) { + break; + } else { + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + /* <2> Query firmare size */ + kalFirmwareSize(prGlueInfo, &u4FwSize); + /* <3> Use vmalloc for allocating large memory trunk */ + prFwBuffer = vmalloc(ALIGN_4(u4FwSize)); + /* <4> Load image binary into buffer */ + if (kalFirmwareLoad(prGlueInfo, prFwBuffer, 0, &u4FwSize) != WLAN_STATUS_SUCCESS) { + vfree(prFwBuffer); + kalFirmwareClose(prGlueInfo); + break; + } + /* <5> write back info */ + *pu4FileLength = u4FwSize; + *ppvMapFileBuf = prFwBuffer; + + return prFwBuffer; + } + + } while (FALSE); + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to unload firmware image mapped memory +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param pvFwHandle Pointer to mapping handle +* \param pvMapFileBuf Pointer to memory-mapped firmware image +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +kalFirmwareImageUnmapping ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID prFwHandle, + IN PVOID pvMapFileBuf + ) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + + /* pvMapFileBuf might be NULL when file doesn't exist */ + if(pvMapFileBuf) { + vfree(pvMapFileBuf); + } + + kalFirmwareClose(prGlueInfo); +} + +#endif + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to load firmware image +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image +* \param pu4FileLength File length and memory mapped length as well + +* \retval Map File Handle, used for unammping +*/ +/*----------------------------------------------------------------------------*/ + +PVOID +kalFirmwareImageMapping ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PPVOID ppvMapFileBuf, + OUT PUINT_32 pu4FileLength + ) +{ + INT_32 i4Ret = 0; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + do { + GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; + prGlueInfo->prFw = NULL; + + /* <1> Open firmware */ + i4Ret = request_firmware(&prGlueInfo->prFw, CFG_FW_FILENAME, &prHifInfo->func->dev); + + if (i4Ret) { + printk (KERN_INFO DRV_NAME"fw %s:request failed %d\n", CFG_FW_FILENAME, i4Ret); + break; + } else { + *pu4FileLength = prGlueInfo->prFw->size; + *ppvMapFileBuf = prGlueInfo->prFw->data; + return prGlueInfo->prFw->data; + } + + } while (FALSE); + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to unload firmware image mapped memory +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param pvFwHandle Pointer to mapping handle +* \param pvMapFileBuf Pointer to memory-mapped firmware image +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +kalFirmwareImageUnmapping ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID prFwHandle, + IN PVOID pvMapFileBuf + ) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + ASSERT(pvMapFileBuf); + + release_firmware(prGlueInfo->prFw); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to acquire +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[out] pu4Flags Pointer of a variable for saving IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT PUINT_32 pu4Flags + ) +{ + UINT_32 u4Flags = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Flags); + + if (rLockCategory < SPIN_LOCK_NUM) { + +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_lock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_lock_irqsave(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *pu4Flags = u4Flags; + } + + return; +} /* end of kalAcquireSpinLock() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[in] u4Flags Saved IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalReleaseSpinLock ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN UINT_32 u4Flags + ) +{ + ASSERT(prGlueInfo); + + if (rLockCategory < SPIN_LOCK_NUM) { + +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_unlock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_unlock_irqrestore(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + } + + return; +} /* end of kalReleaseSpinLock() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to update +* current MAC address. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pucMacAddr Pointer of current MAC address +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateMACAddress ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucMacAddr + ) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if(UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) { + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); + } + + return; +} + + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief To query the packet information for offload related parameters. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalQueryTxChksumOffloadParam ( + IN PVOID pvPacket, + OUT PUINT_8 pucFlag + ) +{ + struct sk_buff *skb = (struct sk_buff *) pvPacket; + UINT_8 ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + if (skb->ip_summed == CHECKSUM_HW) +#else + if (skb->ip_summed == CHECKSUM_PARTIAL) +#endif + { + +#if DBG + /* Kevin: do double check, we can remove this part in Normal Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so + * we'll process IP packet only. + */ + if (skb->protocol != __constant_htons(ETH_P_IP)) { + //printk("Wrong skb->protocol( = %08x) for TX Checksum Offload.\n", skb->protocol); + } + else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + + return; +} /* kalQueryChksumOffloadParam */ + + +//4 2007/10/8, mikewu, this is rewritten by Mike +/*----------------------------------------------------------------------------*/ +/*! +* \brief To update the checksum offload status to the packet to be indicated to OS. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRxCSUMOffloadParam ( + IN PVOID pvPacket, + IN ENUM_CSUM_RESULT_T aeCSUM[] + ) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + ASSERT(pvPacket); + + if ( (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)&& + ( (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS)) ) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + else { + skb->ip_summed = CHECKSUM_NONE; +#if DBG + if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) { + DBGLOG(RX, TRACE, ("RX: \"non-IPv4/IPv6\" Packet\n")); + } + else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) { + DBGLOG(RX, TRACE, ("RX: \"bad IP Checksum\" Packet\n")); + } + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + DBGLOG(RX, TRACE, ("RX: \"bad TCP Checksum\" Packet\n")); + } + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + DBGLOG(RX, TRACE, ("RX: \"bad UDP Checksum\" Packet\n")); + } + else { + + } +#endif + } + +} /* kalUpdateRxCSUMOffloadParam */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to free packet allocated from kalPacketAlloc. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of the packet descriptor +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalPacketFree( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket + ) +{ + dev_kfree_skb((struct sk_buff *) pvPacket); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Only handles driver own creating packet (coalescing buffer). +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param u4Size Pointer of Packet Handle +* \param ppucData Status Code for OS upper layer +* +* \return NULL: Failed to allocate skb, Not NULL get skb +*/ +/*----------------------------------------------------------------------------*/ +PVOID +kalPacketAlloc ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Size, + OUT PUINT_8 *ppucData + ) +{ + struct sk_buff *prSkb = dev_alloc_skb(u4Size); + + if (prSkb) { + *ppucData = (PUINT_8) (prSkb->data); + } +#if DBG +{ + PUINT_32 pu4Head = (PUINT_32)&prSkb->cb[0]; + *pu4Head = (UINT_32)prSkb->head; + DBGLOG(RX, TRACE, ("prSkb->head = %#lx, prSkb->cb = %#lx\n", (UINT_32)prSkb->head, *pu4Head)); +} +#endif + return (PVOID) prSkb; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Process the received packet for indicating to OS. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] pvPacket Pointer of the packet descriptor +* \param[in] pucPacketStart The starting address of the buffer of Rx packet. +* \param[in] u4PacketLen The packet length. +* \param[in] pfgIsRetain Is the packet to be retained. +* \param[in] aerCSUM The result of TCP/ IP checksum offload. +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalProcessRxPacket ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, + IN PUINT_8 pucPacketStart, + IN UINT_32 u4PacketLen, + //IN PBOOLEAN pfgIsRetain, + IN BOOLEAN fgIsRetain, + IN ENUM_CSUM_RESULT_T aerCSUM[] + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + + skb->data = (unsigned char *)pucPacketStart; + skb->tail = (unsigned char *) ((UINT_32) (pucPacketStart + u4PacketLen)); + skb->len = (unsigned int)u4PacketLen; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + kalUpdateRxCSUMOffloadParam(skb, aerCSUM); +#endif + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate an array of received packets is available for higher +* level protocol uses. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] apvPkts The packet array to be indicated +* \param[in] ucPktNum The number of packets to be indicated +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalRxIndicatePkts ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID apvPkts[], + IN UINT_8 ucPktNum + ) +{ + UINT_8 ucIdx = 0; + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + for(ucIdx = 0; ucIdx < ucPktNum; ucIdx++) { + prSkb = apvPkts[ucIdx]; +#if DBG + do { + PUINT_8 pu4Head = (PUINT_8)&prSkb->cb[0]; + UINT_32 u4HeadValue = 0; + kalMemCopy(&u4HeadValue, pu4Head, sizeof(u4HeadValue)); + DBGLOG(RX, TRACE, ("prSkb->head = 0x%p, prSkb->cb = 0x%lx\n", pu4Head, u4HeadValue)); + } while (0); +#endif + + if (GLUE_GET_PKT_IS_P2P(prSkb)) { + /* P2P */ +#if CFG_ENABLE_WIFI_DIRECT + if(prGlueInfo->prAdapter->fgIsP2PRegistered) { + prNetDev = kalP2PGetDevHdlr(prGlueInfo); + } + + //prNetDev->stats.rx_bytes += prSkb->len; + //prNetDev->stats.rx_packets++; + prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.rx_packets++; + +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } + else if (GLUE_GET_PKT_IS_PAL(prSkb)) { + /* BOW */ +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_SEPARATE_DATA_PATH + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + prNetDev = prGlueInfo->rBowInfo.prDevHandler; + } +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } + else { + /* AIS */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + } + + prNetDev->last_rx = jiffies; + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + //DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); + DBGLOG(RX, EVENT, ("kalRxIndicatePkts len = %d\n", prSkb->len)); + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, ("Rx sk_buff->len: %d\n", prSkb->len)); + DBGLOG(BOW, TRACE, ("Rx sk_buff->data_len: %d\n", prSkb->data_len)); + DBGLOG(BOW, TRACE, ("Rx sk_buff->data:\n")); + + for(i = 0; i < prSkb->len && i < 64; i++) + { + LOG_FUNC("%02x ", prSkb->data[i]); + + if((i+1)%16 ==0) + { + LOG_FUNC("\n"); + } + } + + LOG_FUNC("\n"); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + if(!in_interrupt()){ + netif_rx_ni(prSkb); /* only in non-interrupt context */ + } + else { + netif_rx(prSkb); + } +#else + netif_rx(prSkb); +#endif + + wlanReturnPacket(prGlueInfo->prAdapter, NULL); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Called by driver to indicate event to upper layer, for example, the wpa +* supplicant or wireless tools. +* +* \param[in] pvAdapter Pointer to the adapter descriptor. +* \param[in] eStatus Indicated status. +* \param[in] pvBuf Indicated message buffer. +* \param[in] u4BufLen Indicated message buffer size. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateStatusAndComplete ( + IN P_GLUE_INFO_T prGlueInfo, + IN WLAN_STATUS eStatus, + IN PVOID pvBuf, + IN UINT_32 u4BufLen + ) +{ + UINT_32 bufLen; + P_PARAM_STATUS_INDICATION_T pStatus = (P_PARAM_STATUS_INDICATION_T) pvBuf; + P_PARAM_AUTH_EVENT_T pAuth = (P_PARAM_AUTH_EVENT_T) pStatus; + P_PARAM_PMKID_CANDIDATE_LIST_T pPmkid = + (P_PARAM_PMKID_CANDIDATE_LIST_T) (pStatus + 1); + PARAM_MAC_ADDRESS arBssid; + struct cfg80211_scan_request *prScanRequest = NULL; + PARAM_SSID_T ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss; + UINT_8 ucChannelNum; + P_BSS_DESC_T prBssDesc = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + + ASSERT(prGlueInfo); + + switch (eStatus) { + case WLAN_STATUS_ROAM_OUT_FIND_BEST: + case WLAN_STATUS_MEDIA_CONNECT: + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_CONNECTED; + + /* indicate assoc event */ + wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBssid, + &arBssid[0], + sizeof(arBssid), + &bufLen); + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, arBssid, bufLen); + + /* switch netif on */ + netif_carrier_on(prGlueInfo->prDevHandler); + + do { + /* print message on console */ + wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuerySsid, + &ssid, + sizeof(ssid), + &bufLen); + + ssid.aucSsid[(ssid.u4SsidLen >= PARAM_MAX_LEN_SSID) ? + (PARAM_MAX_LEN_SSID - 1) : ssid.u4SsidLen ] = '\0'; + DBGLOG(INIT, INFO, ("[wifi] %s netif_carrier_on [ssid:%s " MACSTR "]\n", + prGlueInfo->prDevHandler->name, + ssid.aucSsid, + MAC2STR(arBssid))); + } while(0); + + if(prGlueInfo->fgIsRegistered == TRUE) { + /* retrieve channel */ + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + if(ucChannelNum <= 14) { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } + else { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + /* ensure BSS exists */ + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + + if(bss == NULL) { + /* create BSS on-the-fly */ + prBssDesc = wlanGetTargetBssDescByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if(prBssDesc != NULL) { + bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), + prChannel, + arBssid, + 0, /* TSF */ + WLAN_CAPABILITY_ESS, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); + } + } + + /* CFG80211 Indication */ + if(eStatus == WLAN_STATUS_MEDIA_CONNECT + && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) { + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + else if(eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST + && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTED) { + #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0) + + cfg80211_roamed_bss(prGlueInfo->prDevHandler, + bss, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + GFP_KERNEL); + #else + struct ieee80211_channel *prChannel = NULL; + UINT_8 ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if(ucChannelNum <= 14) { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } + else { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + cfg80211_roamed(prGlueInfo->prDevHandler, + prChannel, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + GFP_KERNEL); + #endif + } + } + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0); + /* For CR 90 and CR99, While supplicant do reassociate, driver will do netif_carrier_off first, + after associated success, at joinComplete(), do netif_carier_on, + but for unknown reason, the supplicant 1x pkt will not called the driver + hardStartXmit, for template workaround these bugs, add this compiling flag + */ + /* switch netif off */ + +#if 1 /* CONSOLE_MESSAGE */ + DBGLOG(INIT, INFO, ("[wifi] %s netif_carrier_off\n", prGlueInfo->prDevHandler->name)); +#endif + + netif_carrier_off(prGlueInfo->prDevHandler); + + if(prGlueInfo->fgIsRegistered == TRUE + && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTED) { + /* CFG80211 Indication */ + cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, GFP_KERNEL); + } + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + + break; + + case WLAN_STATUS_SCAN_COMPLETE: + /* indicate scan complete event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0); + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if(prGlueInfo->prScanRequest != NULL) { + prScanRequest = prGlueInfo->prScanRequest; + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 2. then CFG80211 Indication */ + if(prScanRequest != NULL) { + cfg80211_scan_done(prScanRequest, FALSE); + } + break; + case WLAN_STATUS_CONNECT_INDICATION: + /* indicate AIS Jion fail event */ + if(prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) { + cfg80211_connect_result(prGlueInfo->prDevHandler, + prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->aucBSSID, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + REASON_CODE_UNSPECIFIED, + GFP_KERNEL); + } + break; + + #if 0 + case WLAN_STATUS_MSDU_OK: + if (netif_running(prGlueInfo->prDevHandler)) { + netif_wake_queue(prGlueInfo->prDevHandler); + } + break; + #endif + + case WLAN_STATUS_MEDIA_SPECIFIC_INDICATION: + if (pStatus) { + switch (pStatus->eStatusType) { + case ENUM_STATUS_TYPE_AUTHENTICATION: + /* + printk(KERN_NOTICE "ENUM_STATUS_TYPE_AUTHENTICATION: L(%ld) [" MACSTR "] F:%lx\n", + pAuth->Request[0].Length, + MAC2STR(pAuth->Request[0].Bssid), + pAuth->Request[0].Flags); + */ + /* indicate (UC/GC) MIC ERROR event only */ + if ((pAuth->arRequest[0].u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) || + (pAuth->arRequest[0].u4Flags == + PARAM_AUTH_REQUEST_GROUP_ERROR)) { + cfg80211_michael_mic_failure(prGlueInfo->prDevHandler, NULL, + (pAuth->arRequest[0].u4Flags == PARAM_AUTH_REQUEST_PAIRWISE_ERROR) ? NL80211_KEYTYPE_PAIRWISE : NL80211_KEYTYPE_GROUP, + 0, NULL, GFP_KERNEL); + wext_indicate_wext_event(prGlueInfo, + IWEVMICHAELMICFAILURE, + (unsigned char *)&pAuth->arRequest[0], + pAuth->arRequest[0].u4Length); + } + break; + + case ENUM_STATUS_TYPE_CANDIDATE_LIST: + /* + printk(KERN_NOTICE "Param_StatusType_PMKID_CandidateList: Ver(%ld) Num(%ld)\n", + pPmkid->u2Version, + pPmkid->u4NumCandidates); + if (pPmkid->u4NumCandidates > 0) { + printk(KERN_NOTICE "candidate[" MACSTR "] preAuth Flag:%lx\n", + MAC2STR(pPmkid->arCandidateList[0].rBSSID), + pPmkid->arCandidateList[0].fgFlags); + } + */ + { + UINT_32 i = 0; + + P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T)&pPmkid->arCandidateList[0]; + + for (i=0; iu4NumCandidates; i++) { + wext_indicate_wext_event(prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *)&pPmkid->arCandidateList[i], + pPmkid->u4NumCandidates); + prPmkidCand += sizeof(PARAM_PMKID_CANDIDATE_T); + } + } + break; + + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + /* + printk(KERN_NOTICE "unknown media specific indication type:%x\n", + pStatus->StatusType); + */ + break; + } + } + else { + /* + printk(KERN_WARNING "media specific indication buffer NULL\n"); + */ + } + break; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case WLAN_STATUS_BWCS_UPDATE: + { + wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, sizeof(PTA_IPC_T)); + } + + break; + +#endif + + default: + /* + printk(KERN_WARNING "unknown indication:%lx\n", eStatus); + */ + break; + } +} /* kalIndicateStatusAndComplete */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update the (re)association request +* information to the structure used to query and set +* OID_802_11_ASSOCIATION_INFORMATION. +* +* \param[in] prGlueInfo Pointer to the Glue structure. +* \param[in] pucFrameBody Pointer to the frame body of the last (Re)Association +* Request frame from the AP. +* \param[in] u4FrameBodyLen The length of the frame body of the last +* (Re)Association Request frame. +* \param[in] fgReassocRequest TRUE, if it is a Reassociation Request frame. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateReAssocReqInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, + IN BOOLEAN fgReassocRequest + ) +{ + PUINT_8 cp; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + else { + if (u4FrameBodyLen < 9) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2*/ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } + else { + /* Capability information field 2 */ + /* Listen interval field 2*/ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); + + if(u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to update the (re)association +* response information to the structure used to reply with +* cfg80211_connect_result +* +* @param prGlueInfo Pointer to adapter descriptor +* @param pucFrameBody Pointer to the frame body of the last (Re)Association +* Response frame from the AP +* @param u4FrameBodyLen The length of the frame body of the last +* (Re)Association Response frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateReAssocRspInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen + ) +{ + UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ + UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4RspIeLength = 0; + + if(u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4RspIeLength = u4IELength; + kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalSendCompleteAndAwakeQueue ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket + ) +{ + + struct net_device *prDev = NULL; + struct sk_buff *prSkb = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucNetworkType = 0; + BOOLEAN fgIsValidDevice = TRUE; + + + ASSERT(pvPacket); + ASSERT(prGlueInfo->i4TxPendingFrameNum); + + prSkb = (struct sk_buff *) pvPacket; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + u2QueueIdx = skb_get_queue_mapping(prSkb); +#endif + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (GLUE_GET_PKT_IS_PAL(prSkb)) { + ucNetworkType = NETWORK_TYPE_BOW_INDEX; + } else if (GLUE_GET_PKT_IS_P2P(prSkb)) { + ucNetworkType = NETWORK_TYPE_P2P_INDEX; + +#if CFG_ENABLE_WIFI_DIRECT + /* in case packet was sent after P2P device is unregistered */ + if(prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + fgIsValidDevice = FALSE; + } +#endif + } else { + ucNetworkType = NETWORK_TYPE_AIS_INDEX; + } + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); + prDev = prSkb->dev; + + ASSERT(prDev); + + if(fgIsValidDevice == TRUE) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26) + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx] <= CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD) { + netif_wake_subqueue(prDev, u2QueueIdx); + } +#else + if (prGlueInfo->i4TxPendingFrameNum < CFG_TX_STOP_NETIF_QUEUE_THRESHOLD) { + netif_wake_queue(prGlueInfo->prDevHandler); + } +#endif + } + + + dev_kfree_skb((struct sk_buff *) pvPacket); + + DBGLOG(TX, EVENT, ("----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum)); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Copy Mac Address setting from registry. It's All Zeros in Linux. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \param[out] paucMacAddr Pointer to the Mac Address buffer +* +* \retval WLAN_STATUS_SUCCESS +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalQueryRegistryMacAddr ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_8 paucMacAddr + ) +{ + UINT_8 aucZeroMac[MAC_ADDR_LEN] = {0,0,0,0,0,0} + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((PVOID) paucMacAddr, (PVOID)aucZeroMac, MAC_ADDR_LEN); + + return; +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read external configuration, ex. NVRAM or file +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalReadExtCfg ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + /* External data is given from user space by ioctl or /proc, not read by + driver. + */ + if (0 != prGlueInfo->u4ExtCfgLength) { + DBGLOG(INIT, TRACE, ("Read external configuration data -- OK\n")); + } + else { + DBGLOG(INIT, TRACE, ("Read external configuration data -- fail\n")); + } + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information, including +* user priority, packet length, destination address, 802.1x and BT over Wi-Fi +* or not. +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pucPriorityParam User priority +* @param pu4PacketLen Packet length +* @param pucEthDestAddr Destination address +* @param pfgIs1X 802.1x packet or not +* @param pfgIsPAL BT over Wi-Fi packet or not +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ + +BOOL +kalQoSFrameClassifierAndPacketInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, + OUT PUINT_8 pucNetworkType + ) +{ + + UINT_32 u4PacketLen; + + + UINT_8 ucUserPriority = USER_PRIORITY_DEFAULT; /* Default */ + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *) prPacket; + PUINT_8 aucLookAheadBuf = NULL; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETH_HLEN) { + DBGLOG(INIT, WARN, ("Invalid Ether packet length: %d\n", u4PacketLen)); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + *pfgIsPAL = FALSE; + //4 <3> Obtain the User Priority for WMM + u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + + if ((u2EtherTypeLen == ETH_P_IP) && + (u4PacketLen >= LOOK_AHEAD_LEN)) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucIpVersion; + + ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + //printk ("ip version %x\n", ucIpVersion); + if (ucIpVersion == IPVERSION) { + UINT_8 ucIpTos; + /* Get the DSCP value from the header of IP packet. */ + ucIpTos = pucIpHdr[1]; + ucUserPriority = ((ucIpTos & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET); + } + + /* TODO(Kevin): Add TSPEC classifier here */ + } + else if (u2EtherTypeLen == ETH_P_1X) { /* For Port Control */ + //DBGLOG(REQ, TRACE, ("Tx 1x\n")); + *pfgIs1X = TRUE; + } + else if (u2EtherTypeLen == ETH_P_PRE_1X) { /* For Pre 1x pkt */ + //DBGLOG(REQ, TRACE, ("Tx Pre-1x\n")); + *pfgIs1X = TRUE; + } +#if CFG_SUPPORT_WAPI + else if (u2EtherTypeLen == ETH_WPI_1X) { + *pfgIs1X = TRUE; + } +#endif + else if (u2EtherTypeLen <= 1500) { /* 802.3 Frame */ + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + + if(ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && + aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) { + + UINT_16 tmp = ((aucLookAheadBuf[ETH_SNAP_OFFSET + 3] << 8) | aucLookAheadBuf[ETH_SNAP_OFFSET + 4]); + + *pfgIsPAL = TRUE; + ucUserPriority = (UINT_8)prSkb->priority; + + if (tmp == BOW_PROTOCOL_ID_SECURITY_FRAME) { + *pfgIs1X = TRUE; + } + } + } + + //4 <4> Return the value of Priority Parameter. + *pucPriorityParam = ucUserPriority; + + //4 <5> Retrieve Packet Information - DA + /* Packet Length/ Destination Address */ + *pu4PacketLen = u4PacketLen; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + + //<6> Network type +#if CFG_ENABLE_BT_OVER_WIFI + if(*pfgIsPAL == TRUE) { + *pucNetworkType = NETWORK_TYPE_BOW_INDEX; + } + else +#endif + { +#if CFG_ENABLE_WIFI_DIRECT + if(prGlueInfo->prAdapter->fgIsP2PRegistered && GLUE_GET_PKT_IS_P2P(prPacket)) { + *pucNetworkType = NETWORK_TYPE_P2P_INDEX; + } + else +#endif + { + *pucNetworkType = NETWORK_TYPE_AIS_INDEX; + } + } + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +VOID +kalOidComplete ( + IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, + IN UINT_32 u4SetQueryInfoLen, + IN WLAN_STATUS rOidStatus + ) +{ + + ASSERT(prGlueInfo); + /* remove timeout check timer */ + wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); + + //if (prGlueInfo->u4TimeoutFlag != 1) { + prGlueInfo->rPendStatus = rOidStatus; + complete(&prGlueInfo->rPendComp); + prGlueInfo->u4OidCompleteFlag = 1; + //} + /* else let it timeout on kalIoctl entry */ +} + +VOID +kalOidClearance( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + //if (prGlueInfo->u4TimeoutFlag != 1) { + //clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag); + if (prGlueInfo->u4OidCompleteFlag != 1) { + complete(&prGlueInfo->rPendComp); + } + //} +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to transfer linux ioctl to OID, and we +* need to specify the behavior of the OID by ourself +* +* @param prGlueInfo Pointer to the glue structure +* @param pvInfoBuf Data buffer +* @param u4InfoBufLen Data buffer length +* @param fgRead Is this a read OID +* @param fgWaitResp does this OID need to wait for values +* @param fgCmd does this OID compose command packet +* @param pu4QryInfoLen The data length of the return values +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ + +// todo: enqueue the i/o requests for multiple processes access +// +// currently, return -1 +// + +//static GL_IO_REQ_T OidEntry; + +WLAN_STATUS +kalIoctl (IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOL fgRead, + IN BOOL fgWaitResp, + IN BOOL fgCmd, + IN BOOL fgIsP2pOid, + OUT PUINT_32 pu4QryInfoLen + ) +{ + P_GL_IO_REQ_T prIoReq = NULL; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + + + //GLUE_SPIN_LOCK_DECLARATION(); + ASSERT(prGlueInfo); + + + + /* <1> Check if driver is halt */ + + //if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + // return WLAN_STATUS_ADAPTER_NOT_READY; + //} + + if (down_interruptible(&g_halt_sem)) { + return WLAN_STATUS_FAILURE; + } + + + if (g_u4HaltFlag) { + up(&g_halt_sem); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if(down_interruptible(&prGlueInfo->ioctl_sem)) { + up(&g_halt_sem); + return WLAN_STATUS_FAILURE; + } + + /* <2> TODO: thread-safe */ + + /* <3> point to the OidEntry of Glue layer */ + + prIoReq = &(prGlueInfo->OidEntry); + + ASSERT(prIoReq); + + /* <4> Compose the I/O request */ + prIoReq->prAdapter = prGlueInfo->prAdapter; + prIoReq->pfnOidHandler = pfnOidHandler; + prIoReq->pvInfoBuf = pvInfoBuf; + prIoReq->u4InfoBufLen = u4InfoBufLen; + prIoReq->pu4QryInfoLen = pu4QryInfoLen; + prIoReq->fgRead = fgRead; + prIoReq->fgWaitResp= fgWaitResp; + prIoReq->rStatus = WLAN_STATUS_FAILURE; +#if CFG_ENABLE_WIFI_DIRECT + prIoReq->fgIsP2pOid = fgIsP2pOid; +#endif + + /* <5> Reset the status of pending OID */ + prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; + //prGlueInfo->u4TimeoutFlag = 0; + prGlueInfo->u4OidCompleteFlag = 0; + + /* <6> Check if we use the command queue */ + prIoReq->u4Flag = fgCmd; + + /* <7> schedule the OID bit */ + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag); + + /* <8> Wake up tx thread to handle kick start the I/O request */ + wake_up_interruptible(&prGlueInfo->waitq); + + /* <9> Block and wait for event or timeout, current the timeout is 5 secs */ + //if (wait_for_completion_interruptible_timeout(&prGlueInfo->rPendComp, 5 * KAL_HZ)) { + //if (!wait_for_completion_interruptible(&prGlueInfo->rPendComp)) { + wait_for_completion(&prGlueInfo->rPendComp); { + /* Case 1: No timeout. */ + /* if return WLAN_STATUS_PENDING, the status of cmd is stored in prGlueInfo */ + if (prIoReq->rStatus == WLAN_STATUS_PENDING) { + ret = prGlueInfo->rPendStatus; + } else { + ret = prIoReq->rStatus; + } + } + #if 0 + else { + /* Case 2: timeout */ + /* clear pending OID's cmd in CMD queue */ + if (fgCmd) { + prGlueInfo->u4TimeoutFlag = 1; + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + } + ret = WLAN_STATUS_FAILURE; + } + #endif + + up(&prGlueInfo->ioctl_sem); + up(&g_halt_sem); + + + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending security frames +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalClearSecurityFrames( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + // Clear pending security frames in prGlueInfo->rCmdQueue + prCmdQue = &prGlueInfo->rCmdQueue; + + + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear pending security frames +* belongs to dedicated network type +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param eNetworkTypeIdx Network Type Index +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalClearSecurityFramesByNetType( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(prGlueInfo); + + // Clear pending security frames in prGlueInfo->rCmdQueue + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME && + prCmdInfo->eNetworkType == eNetworkTypeIdx) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending management frames +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalClearMgmtFrames( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + // Clear pending management frames in prGlueInfo->rCmdQueue + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending management frames +* belongs to dedicated network type +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalClearMgmtFramesByNetType ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + // Clear pending management frames in prGlueInfo->rCmdQueue + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME && + prCmdInfo->eNetworkType == eNetworkTypeIdx) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByNetType */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a kernel thread function for handling command packets +* Tx requests and interrupt events +* +* @param data data pointer to private data of tx_thread +* +* @retval If the function succeeds, the return value is 0. +* Otherwise, an error code is returned. +* +*/ +/*----------------------------------------------------------------------------*/ + +int tx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_GL_IO_REQ_T prIoReq = NULL; + P_QUE_T prTxQueue = NULL; + P_QUE_T prCmdQue = NULL; + + int ret = 0; + + BOOLEAN fgNeedHwAccess = FALSE; + + struct sk_buff *prSkb = NULL; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + current->flags |= PF_NOFREEZE; + + DBGLOG(INIT, INFO, ("tx_thread starts running... \n")); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->u4Flag)) { + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + } +#endif + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, ("tx_thread should stop now...\n")); + break; + } + + /* + * sleep on waitqueue if no events occurred. Event contain (1) GLUE_FLAG_INT + * (2) GLUE_FLAG_OID (3) GLUE_FLAG_TXREQ (4) GLUE_FLAG_HALT + * + */ + + ret = wait_event_interruptible(prGlueInfo->waitq, + (prGlueInfo->u4Flag != 0)); + +#if CFG_DBG_GPIO_PINS + /* TX thread Wake up */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_LOW); +#endif +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->u4Flag)) { + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + } + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->u4Flag)) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter); + } + + +#endif + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, ("<1>tx_thread should stop now...\n")); + break; + } + + fgNeedHwAccess = FALSE; + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag)) { + + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* the Wi-Fi interrupt is already disabled in mmc thread, + so we set the flag only to enable the interrupt later */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + //wlanISR(prGlueInfo->prAdapter, TRUE); + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, ("ignore pending interrupt\n")); + } + else { + + wlanIST(prGlueInfo->prAdapter); + } + } + + /* transfer ioctl to OID request */ + #if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + printk(KERN_INFO DRV_NAME"<2>tx_thread should stop now...\n"); + break; + } + #endif + + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag)) { + /* get current prIoReq */ + prIoReq = &(prGlueInfo->OidEntry); +#if CFG_ENABLE_WIFI_DIRECT + if(prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE + && prIoReq->fgIsP2pOid == TRUE) { + /* if this Oid belongs to p2p and p2p module is removed + * do nothing, + */ + } + else +#endif + { + if (FALSE == prIoReq->fgRead) { + prIoReq->rStatus = wlanSetInformation( + prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } else { + prIoReq->rStatus = wlanQueryInformation( + prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } + + if (prIoReq->rStatus != WLAN_STATUS_PENDING) { + complete(&prGlueInfo->rPendComp); + } + else { + wlanoidTimeoutCheck(prGlueInfo->prAdapter, prIoReq->pfnOidHandler); + } + } + } + + } while (FALSE); + + + /* + * + * if TX request, clear the TXREQ flag. TXREQ set by kalSetEvent/GlueSetEvent + * indicates the following requests occur + * + */ + #if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + printk(KERN_INFO DRV_NAME"<3>tx_thread should stop now...\n"); + break; + } + #endif + + if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->u4Flag)) + { + + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ + do { + if (prCmdQue->u4NumElem > 0) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } + } while (FALSE); + + /* Handle Packet Tx */ + { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQueue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + ASSERT(prQueueEntry); + if (NULL == prQueueEntry) { + break; + } + + prSkb = (struct sk_buff *) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (NULL == prSkb) { + DBGLOG(INIT, WARN, ("prSkb == NULL in tx\n")); + continue; + } + + if(wlanEnqueueTxPacket(prGlueInfo->prAdapter, + (P_NATIVE_PACKET)prSkb) == WLAN_STATUS_RESOURCES) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_HEAD(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) { + wlanTxPendingPackets(prGlueInfo->prAdapter, &fgNeedHwAccess); + } + } + + } + + /* Process RX, In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't do reset */ + if (fgNeedHwAccess == TRUE) { + wlanReleasePowerControl(prGlueInfo->prAdapter); + } + + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->u4Flag)) { + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); + } + + #if CFG_DBG_GPIO_PINS + /* TX thread go to sleep */ + if (!prGlueInfo->u4Flag){ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH); + } + #endif + } + + #if 0 + if (fgNeedHwAccess == TRUE) { + wlanReleasePowerControl(prGlueInfo->prAdapter); + } + #endif + + /* flush the pending TX packets */ + if (prGlueInfo->i4TxPendingFrameNum > 0) { + kalFlushPendingTxPackets(prGlueInfo); + } + + /* flush pending security frames */ + if (prGlueInfo->i4TxPendingSecurityFrameNum > 0) { + kalClearSecurityFrames(prGlueInfo); + } + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + + /* In linux, we don't need to free sk_buff by ourself */ + + DBGLOG(INIT, INFO, ("mtk_sdiod stops\n")); + complete(&prGlueInfo->rHaltComp); + + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to check if card is removed +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval TRUE: card is removed +* FALSE: card is still attached +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalIsCardRemoved( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return FALSE; + // Linux MMC doesn't have removal notification yet +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to send command to firmware for overriding netweork address + * + * \param pvGlueInfo Pointer of GLUE Data Structure + + * \retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalRetrieveNetworkAddress( + IN P_GLUE_INFO_T prGlueInfo, + IN OUT PARAM_MAC_ADDRESS * prMacAddr + ) +{ + ASSERT(prGlueInfo); + + if(prGlueInfo->fgIsMacAddrOverride == FALSE) { + #if !defined(CONFIG_X86) + UINT_32 i; + BOOLEAN fgIsReadError = FALSE; + + for(i = 0 ; i < MAC_ADDR_LEN ; i+=2) { + if(kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8)prMacAddr) + i)) == FALSE) { + fgIsReadError = TRUE; + break; + } + } + + if(fgIsReadError == TRUE) { + return FALSE; + } + else { + return TRUE; + } + #else + /* x86 Linux doesn't need to override network address so far */ + return FALSE; + #endif + } + else { + COPY_MAC_ADDR(prMacAddr, prGlueInfo->rMacAddrOverride); + + return TRUE; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to flush pending TX packets in glue layer +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalFlushPendingTxPackets( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_QUE_T prTxQue; + P_QUE_ENTRY_T prQueueEntry; + PVOID prPacket; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (prGlueInfo->i4TxPendingFrameNum) { + while (TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + if (prQueueEntry == NULL) { + break; + } + + prPacket = GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + + kalSendComplete(prGlueInfo, + prPacket, + WLAN_STATUS_NOT_ACCEPTED); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is get indicated media state +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T +kalGetMediaStateIndicated( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->eParamMediaStateIndicated; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set indicated media state +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalSetMediaStateIndicated( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate + ) +{ + ASSERT(prGlueInfo); + + prGlueInfo->eParamMediaStateIndicated = eParamMediaStateIndicate; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear pending OID staying in command queue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalOidCmdClearance( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T)NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + + if (((P_CMD_INFO_T)prQueueEntry)->fgIsOid) { + prCmdInfo = (P_CMD_INFO_T)prQueueEntry; + break; + } + else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + if (prCmdInfo) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + } + else { + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_NOT_ACCEPTED); + } + + prGlueInfo->u4OidCompleteFlag = 1; + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to insert command into prCmdQueue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* prQueueEntry Pointer of queue entry to be inserted +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalEnqueueCommand( + IN P_GLUE_INFO_T prGlueInfo, + IN P_QUE_ENTRY_T prQueueEntry + ) +{ + P_QUE_T prCmdQue; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Handle EVENT_ID_ASSOC_INFO event packet by indicating to OS with +* proper information +* +* @param pvGlueInfo Pointer of GLUE Data Structure +* @param prAssocInfo Pointer of EVENT_ID_ASSOC_INFO Packet +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalHandleAssocInfo( + IN P_GLUE_INFO_T prGlueInfo, + IN P_EVENT_ASSOC_INFO prAssocInfo + ) +{ + // to do +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to get firmware load address from registry +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetFwLoadAddress( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4LoadAddress; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to get firmware start address from registry +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetFwStartAddress( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4StartAddress; +} + +/*----------------------------------------------------------------------------*/ +/*! + * * @brief Notify OS with SendComplete event of the specific packet. Linux should + * * free packets here. + * * + * * @param pvGlueInfo Pointer of GLUE Data Structure + * * @param pvPacket Pointer of Packet Handle + * * @param status Status Code for OS upper layer + * * + * * @return none + * */ +/*----------------------------------------------------------------------------*/ + +/// Todo +VOID +kalSecurityFrameSendComplete ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, + IN WLAN_STATUS rStatus + ) +{ + ASSERT(pvPacket); + + dev_kfree_skb((struct sk_buff *) pvPacket); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +UINT_32 +kalGetTxPendingFrameCount( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return (UINT_32)(prGlueInfo->i4TxPendingFrameNum); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to retrieve the number of pending commands +* (including MMPDU, 802.1X and command packets) +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetTxPendingCmdCount( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_QUE_T prCmdQue; + + ASSERT(prGlueInfo); + prCmdQue = &prGlueInfo->rCmdQueue; + + return prCmdQue->u4NumElem; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Timer Initialization Procedure +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* \param[in] prTimerHandler Pointer to timer handling function, whose only +* argument is "prAdapter" +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ + +//static struct timer_list tickfn; + +VOID +kalOsTimerInitialize ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID prTimerHandler + ) +{ + + ASSERT(prGlueInfo); + + init_timer(&(prGlueInfo->tickfn)); + prGlueInfo->tickfn.function = prTimerHandler; + prGlueInfo->tickfn.data = (unsigned long) prGlueInfo; +} + +// Todo +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* \param[in] rInterval Time out interval from current time. +* +* \retval TRUE Success. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalSetTimer( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Interval + ) +{ + ASSERT(prGlueInfo); + del_timer_sync(&(prGlueInfo->tickfn)); + + prGlueInfo->tickfn.expires = jiffies + u4Interval * HZ / MSEC_PER_SEC; + add_timer(&(prGlueInfo->tickfn)); + + return TRUE; /* success */ +} +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to cancel +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval TRUE : Timer has been canceled +* FALAE : Timer doens't exist +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalCancelTimer( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->u4Flag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >=0) { + return TRUE; + } else { + return FALSE; + } +} +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is a callback function for scanning done +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalScanDone( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN WLAN_STATUS status + ) +{ + ASSERT(prGlueInfo); + + /* check for system configuration for generating error message on scan list */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to generate a random number +* +* \param none +* +* \retval UINT_32 +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalRandomNumber( + VOID + ) +{ + UINT_32 number = 0; + + get_random_bytes(&number, 4); + + return number; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief command timeout call-back function + * + * \param[in] prGlueInfo Pointer to the GLUE data structure. + * + * \retval (none) + */ +/*----------------------------------------------------------------------------*/ +VOID +kalTimeoutHandler (unsigned long arg) +{ + + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) arg; + + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->u4Flag); + wake_up_interruptible(&prGlueInfo->waitq); + + return; +} + + +VOID +kalSetEvent (P_GLUE_INFO_T pr) { + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->u4Flag); + wake_up_interruptible(&pr->waitq); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if configuration file (NVRAM/Registry) exists +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalIsConfigurationExist( + IN P_GLUE_INFO_T prGlueInfo + ) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + return FALSE; +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Registry information +* +* \param[in] +* prGlueInfo +* +* \return +* Pointer of REG_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_REG_INFO_T +kalGetConfiguration( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve version information of corresponding configuration file +* +* \param[in] +* prGlueInfo +* +* \param[out] +* pu2Part1CfgOwnVersion +* pu2Part1CfgPeerVersion +* pu2Part2CfgOwnVersion +* pu2Part2CfgPeerVersion +* +* \return +* NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetConfigurationVersion( + IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, + OUT PUINT_16 pu2Part2CfgPeerVersion + ) +{ + ASSERT(prGlueInfo); + + ASSERT(pu2Part1CfgOwnVersion); + ASSERT(pu2Part1CfgPeerVersion); + ASSERT(pu2Part2CfgOwnVersion); + ASSERT(pu2Part2CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), + pu2Part1CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), + pu2Part1CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), + pu2Part2CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), + pu2Part2CfgPeerVersion); + + return; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the WPS is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalWSCGetActiveState( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return (prGlueInfo->fgWpsActive); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief update RSSI and LinkQuality to GLUE layer +* +* \param[in] +* prGlueInfo +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN INT_8 cRssi, + IN INT_8 cLinkQuality + ) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + + ASSERT(prGlueInfo); + + switch(eNetTypeIdx) { + case KAL_NETWORK_TYPE_AIS_INDEX: + pStats = (struct iw_statistics *) (&(prGlueInfo->rIwStats)); + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case KAL_NETWORK_TYPE_P2P_INDEX: + pStats = (struct iw_statistics *) (&(prGlueInfo->rP2pIwStats)); + break; +#endif +#endif + default: + break; + + } + + if (pStats) { + pStats->qual.qual = cLinkQuality; + pStats->qual.noise = 0; + pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED; + pStats->qual.level = 0x100 + cRssi; + pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; + } + + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Pre-allocate I/O buffer +* +* \param[in] +* none +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalInitIOBuffer( + VOID + ) +{ + UINT_32 u4Size; + + if(CFG_COALESCING_BUFFER_SIZE >= CFG_RX_COALESCING_BUFFER_SIZE) { + u4Size = CFG_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + } + else { + u4Size = CFG_RX_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + } + + pvIoBuffer = kmalloc(u4Size, GFP_KERNEL); + if(pvIoBuffer) { + pvIoBufferSize = u4Size; + pvIoBufferUsage = 0; + + return TRUE; + } + + return FALSE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free pre-allocated I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUninitIOBuffer( + VOID + ) +{ + if(pvIoBuffer) { + kfree(pvIoBuffer); + + pvIoBuffer = (PVOID) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatch pre-allocated I/O buffer +* +* \param[in] +* u4AllocSize +* +* \return +* PVOID for pointer of pre-allocated I/O buffer +*/ +/*----------------------------------------------------------------------------*/ +PVOID +kalAllocateIOBuffer( + IN UINT_32 u4AllocSize + ) +{ + PVOID ret = (PVOID)NULL; + + if(pvIoBuffer) { + if(u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (PVOID)&(((PUINT_8)(pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } + else { + /* fault tolerance */ + ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release all dispatched I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalReleaseIOBuffer( + IN PVOID pvAddr, + IN UINT_32 u4Size + ) +{ + if(pvIoBuffer) { + pvIoBufferUsage -= u4Size; + } + else { + /* fault tolerance */ + kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChannelList( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, + IN PUINT_8 pucNumOfChannel, + IN P_RF_CHANNEL_INFO_T paucChannelList + ) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + eSpecificBand, + ucMaxChannelNum, + pucNumOfChannel, + paucChannelList); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalIsAPmode( + IN P_GLUE_INFO_T prGlueInfo + ) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif + + return FALSE; +} + + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the MFP is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetMfpSetting( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return (prGlueInfo->rWpaInfo.u4Mfp); +} +#endif + +struct file* +kalFileOpen( + const char* path, + int flags, + int rights) +{ + struct file* filp = NULL; + mm_segment_t oldfs; + int err = 0; + + oldfs = get_fs(); + set_fs(get_ds()); + filp = filp_open(path, flags, rights); + set_fs(oldfs); + if(IS_ERR(filp)) { + err = PTR_ERR(filp); + return NULL; + } + return filp; +} + +VOID +kalFileClose( + struct file* file) +{ + filp_close(file, NULL); +} + +UINT_32 +kalFileRead( + struct file* file, + unsigned long long offset, + unsigned char* data, + unsigned int size) +{ + mm_segment_t oldfs; + int ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_read(file, data, size, &offset); + + set_fs(oldfs); + return ret; +} + +UINT_32 +kalFileWrite( + struct file* file, + unsigned long long offset, + unsigned char* data, + unsigned int size) +{ + mm_segment_t oldfs; + int ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_write(file, data, size, &offset); + + set_fs(oldfs); + return ret; +} + +UINT_32 +kalWriteToFile( + const PUINT_8 pucPath, + BOOLEAN fgDoAppend, + PUINT_8 pucData, + UINT_32 u4Size) +{ + struct file* file = NULL; + UINT_32 ret; + UINT_32 u4Flags = 0; + + if(fgDoAppend) { + u4Flags = O_APPEND; + } + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + ret = kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate BSS-INFO to NL80211 as scanning result +* +* \param[in] +* prGlueInfo +* pucBeaconProbeResp +* u4FrameLen +* +* +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBssInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucBeaconProbeResp, + IN UINT_32 u4FrameLen, + IN UINT_8 ucChannelNum, + IN INT_32 i4SignalStrength + ) +{ + struct wiphy *wiphy; + struct ieee80211_channel *prChannel = NULL; + + ASSERT(prGlueInfo); + wiphy = priv_to_wiphy(prGlueInfo); + + /* search through channel entries */ + if(ucChannelNum <= 14) { + prChannel = ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } + else { + prChannel = ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + if(prChannel != NULL && prGlueInfo->prScanRequest != NULL) { + struct cfg80211_bss *bss; + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, + prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, + i4SignalStrength * 100, + GFP_KERNEL); + + if(!bss) { + DBGLOG(REQ, WARN, ("cfg80211_inform_bss_frame() returned with NULL\n")); + } + else { + cfg80211_put_bss(bss); + } + } + + return; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c new file mode 100755 index 000000000000..a665e721bb91 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c @@ -0,0 +1,5480 @@ +/* +** $Id: @(#) gl_p2p.c@@ +*/ + +/*! \file gl_p2p.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_p2p.c $ +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 17 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** FPB from ALPS.JB to phase 2 release. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 01 09 2012 terry.wu + * [WCXRP00001166] [Wi-Fi] [Driver] cfg80211 integration for p2p newtork + * cfg80211 integration for p2p network. + * + * 12 19 2011 terry.wu + * [WCXRP00001142] [Wi-Fi] [P2P Driver] XOR local admin bit to generate p2p net device MAC + * XOR local administrated bit to generate net device MAC of p2p network. + * + * 12 02 2011 yuche.tsai + * NULL + * Fix possible KE when unload p2p. + * + * 11 24 2011 yuche.tsai + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 16 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Avoid using work thread in set p2p multicast address callback. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix default device name issue. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 11 07 2011 yuche.tsai + * NULL + * [ALPS 00087243] KE in worker thread. + * The multicast address list is scheduled in worker thread. + * Before the worker thread is excuted, if P2P is unloaded, a KE may occur. + * + * 10 26 2011 terry.wu + * [WCXRP00001066] [MT6620 Wi-Fi] [P2P Driver] Fix P2P Oid Issue + * Fix some P2P OID functions didn't raise its flag "fgIsP2pOid" issue. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * . + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channle Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 26 2011 yuche.tsai + * NULL + * Fix bug of parsing secondary device list type issue. + * + * 08 24 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Abort. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue of P2P. + * + * 08 22 2011 chinglan.wang + * NULL + * Fix invitation indication bug.. + * + * 08 16 2011 cp.wu + * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence + * auto channel decision for 2.4GHz hot spot mode + * + * 08 16 2011 chinglan.wang + * NULL + * Add the group id information in the invitation indication. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 08 05 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Add Password ID check for quick connection. + * Also modify some connection policy. + * + * 07 18 2011 chinglan.wang + * NULL + * Add IOC_P2P_GO_WSC_IE (p2p capability). + * + * 06 14 2011 yuche.tsai + * NULL + * Add compile flag to disable persistent group support. + * + * 05 04 2011 chinglan.wang + * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver + * . + * + * 05 02 2011 yuche.tsai + * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. + * Clear formation flag after formation timeout. + * + * 04 22 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * . + * + * 04 21 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * 1. Revise P2P power mode setting. + * 2. Revise fast-PS for concurrent + * + * 04 19 2011 wh.su + * NULL + * Adding length check before doing WPA RSN IE parsing for scan results indicate. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Connection flow refine for Sigma test. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 07 2011 terry.wu + * [WCXRP00000619] [MT6620 Wi-Fi][Driver] fix kernel panic may occur when removing wlan + * Fix kernel panic may occur when removing wlan driver. + * + * 03 31 2011 wh.su + * [WCXRP00000614] [MT6620 Wi-Fi][Driver] P2P: Update beacon content while setting WSC IE + * Update the wsc ie to beacon content. + * + * 03 25 2011 wh.su + * NULL + * add the sample code for set power mode and get power mode. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 22 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Modify formation policy. + * + * 03 22 2011 yuche.tsai + * NULL + * Modify formation policy setting. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 15 2011 wh.su + * [WCXRP00000563] [MT6620 Wi-Fi] [P2P] Set local config method while set password Id ready + * set lccal config method method while set password Id ready. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 15 2011 jeffrey.chang + * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM + * refine queue_select function + * + * 03 13 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * add code for avoid compiling warning. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 10 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Remove unnecessary assert and message. + * + * 03 08 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * support the power save related p2p setting. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify P2P's netdevice functions to support multiple H/W queues + * + * 03 03 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * for get request, the buffer length to be copied is header + payload. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 03 02 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * add a missed break. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 02 25 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * add the Operation channel setting. + * + * 02 23 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * fixed the set int ioctl set index and value map to driver issue. + * + * 02 22 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int from supplicant, and can used to set the p2p paramters + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the ioctl setting that index not map to spec defined config method. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 17 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * modify the structure pointer for set WSC IE. + * + * 02 16 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * fixed the probe request send out without WSC IE issue (at P2P). + * + * 02 09 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * fix typo + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 01 25 2011 terry.wu + * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter + * Add a new module parameter to indicate current runnig mode, P2P or AP. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. + * 2. Call cnmP2pIsPermit() before active P2P network. + * 3. Add channel selection support for AP mode. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 12 15 2010 cp.wu + * NULL + * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 10 2010 george.huang + * NULL + * update iwpriv LP related + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at win XP. + * + * 09 09 2010 cp.wu + * NULL + * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 08 25 2010 cp.wu + * NULL + * add netdev_ops(NDO) for linux kernel 2.6.31 or greater + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 20 2010 cp.wu + * NULL + * correct typo. + * + * 08 20 2010 yuche.tsai + * NULL + * Invert Connection request provision status parameter. + * + * 08 19 2010 cp.wu + * NULL + * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. + * + * 08 18 2010 cp.wu + * NULL + * modify pwp ioctls attribution by removing FIXED_SIZE. + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 17 2010 cp.wu + * NULL + * correct p2p net device registration with NULL pointer access issue. + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * add wext handlers to link P2P set PS profile/ network address function (TBD) + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 12 2010 cp.wu + * NULL + * follow-up with ioctl interface update for Wi-Fi Direct application + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * add basic support for ioctl of getting scan result. (only address and SSID are reporterd though) + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * p2p interface revised to be sync. with HAL + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement private io controls for Wi-Fi Direct + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement wireless extension ioctls in iw_handler form. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include + +#include +//#include +#include "gl_p2p_ioctl.h" + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ARGV_MAX_NUM (4) + +/*For CFG80211 - wiphy parameters*/ +#define MAX_SCAN_LIST_NUM (1) +#define MAX_SCAN_IE_LEN (512) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +/* for cfg80211 - frequency table */ +static struct ieee80211_channel mtk_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct ieee80211_channel mtk_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(169, 0), CHAN5G(173, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0) + +#define MT6620_MCS_INFO \ +{ \ + /* MCS1~7*/ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#if 0 +/*Bandwidth 20Mhz Only*/ +#define MT6620_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = MT6620_MCS_INFO, \ +} +#else +/*Bandwidth 20/40Mhz*/ +#define MT6620_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = MT6620_MCS_INFO, \ +} +#endif + +static struct ieee80211_supported_band mtk_band_2ghz = { + .band = IEEE80211_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = MT6620_HT_CAP, +}; + +static struct ieee80211_supported_band mtk_band_5ghz = { + .band = IEEE80211_BAND_5GHZ, + .channels = mtk_5ghz_a_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_a_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = MT6620_HT_CAP, +}; + +static const UINT_32 cipher_suites[] = { + /* keep WEP first, it may be removed below */ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC +}; + +static struct cfg80211_ops mtk_p2p_config_ops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + /* Froyo */ + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, // 1 st + .change_bss = mtk_p2p_cfg80211_change_bss, + .scan = mtk_p2p_cfg80211_scan, + .remain_on_channel = mtk_p2p_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_p2p_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_p2p_cfg80211_mgmt_tx, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, +#else + .add_beacon = mtk_p2p_cfg80211_add_set_beacon, + .set_beacon = mtk_p2p_cfg80211_add_set_beacon, + .del_beacon = mtk_p2p_cfg80211_stop_ap, +#endif + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_channel = mtk_p2p_cfg80211_set_channel, + .set_bitrate_mask = mtk_p2p_cfg80211_set_bitrate_mask, + .mgmt_frame_register = mtk_p2p_cfg80211_mgmt_frame_register, + .get_station = mtk_p2p_cfg80211_get_station, + // ================ + .add_key = mtk_p2p_cfg80211_add_key, + .get_key = mtk_p2p_cfg80211_get_key, + .del_key = mtk_p2p_cfg80211_del_key, + .set_default_key = mtk_p2p_cfg80211_set_default_key, + .join_ibss = mtk_p2p_cfg80211_join_ibss, + .leave_ibss = mtk_p2p_cfg80211_leave_ibss, + .set_tx_power = mtk_p2p_cfg80211_set_txpower, + .get_tx_power = mtk_p2p_cfg80211_get_txpower, + .set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt, + #ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, + #endif +#endif +}; + + + +/* There isn't a lot of sense in it, but you can transmit anything you like */ +static const struct ieee80211_txrx_stypes +mtk_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + + + +#endif + +/* the legacy wireless extension stuff */ +static const iw_handler rP2PIwStandardHandler[] = { + [SIOCGIWPRIV - SIOCIWFIRST] = mtk_p2p_wext_get_priv, + [SIOCGIWSCAN - SIOCIWFIRST] = mtk_p2p_wext_discovery_results, + [SIOCSIWESSID - SIOCIWFIRST] = mtk_p2p_wext_reconnect, + [SIOCSIWAUTH - SIOCIWFIRST] = mtk_p2p_wext_set_auth, + [SIOCSIWENCODEEXT - SIOCIWFIRST] = mtk_p2p_wext_set_key, + [SIOCSIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_set_powermode, + [SIOCGIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_get_powermode, + [SIOCSIWTXPOW - SIOCIWFIRST] = mtk_p2p_wext_set_txpow, +#if CFG_SUPPORT_P2P_RSSI_QUERY + [SIOCGIWSTATS - SIOCIWFIRST] = mtk_p2p_wext_get_rssi, +#endif + [SIOCSIWMLME - SIOCIWFIRST] = mtk_p2p_wext_mlme_handler, +}; + +static const iw_handler rP2PIwPrivHandler[] = { + [IOC_P2P_CFG_DEVICE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_local_dev_info, + [IOC_P2P_PROVISION_COMPLETE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_provision_complete, + [IOC_P2P_START_STOP_DISCOVERY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_start_stop_discovery, + [IOC_P2P_DISCOVERY_RESULTS - SIOCIWFIRSTPRIV] = mtk_p2p_wext_discovery_results, + [IOC_P2P_WSC_BEACON_PROBE_RSP_IE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_wsc_ie, + [IOC_P2P_CONNECT_DISCONNECT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_connect_disconnect, + [IOC_P2P_PASSWORD_READY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_password_ready, +// [IOC_P2P_SET_PWR_MGMT_PARAM - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_pm_param, + [IOC_P2P_SET_INT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_int, + [IOC_P2P_GET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_get_struct, + [IOC_P2P_SET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_struct, + [IOC_P2P_GET_REQ_DEVICE_INFO - SIOCIWFIRSTPRIV] = mtk_p2p_wext_request_dev_info, +}; + + +static const struct iw_priv_args rP2PIwPrivTable[] = { + { + .cmd = IOC_P2P_CFG_DEVICE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_CFG_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CFG_DEVICE" + }, + { + .cmd = IOC_P2P_START_STOP_DISCOVERY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_REQ_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_DISCOVERY" + }, + { + .cmd = IOC_P2P_DISCOVERY_RESULTS, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_RESULT" + }, + { + .cmd = IOC_P2P_WSC_BEACON_PROBE_RSP_IE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_HOSTAPD_PARAM), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_WSC_IE" + }, + { + .cmd = IOC_P2P_CONNECT_DISCONNECT, + .set_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_CONNECT_DEVICE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CONNECT" + }, + { + .cmd = IOC_P2P_PASSWORD_READY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_PASSWORD_READY), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_PASSWD_RDY" + }, + { + .cmd = IOC_P2P_GET_STRUCT, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "P2P_GET_STRUCT" + }, + { + .cmd = IOC_P2P_SET_STRUCT, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_SET_STRUCT" + }, + { + .cmd = IOC_P2P_GET_REQ_DEVICE_INFO, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_BYTE | (__u16)sizeof(IW_P2P_DEVICE_REQ), + .name = "P2P_GET_REQDEV" + }, + { + /* SET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "set_oid" + }, + { + /* GET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "get_oid" + } +}; + +const struct iw_handler_def mtk_p2p_wext_handler_def = { + .num_standard = (__u16)sizeof(rP2PIwStandardHandler)/sizeof(iw_handler), + .num_private = (__u16)sizeof(rP2PIwPrivHandler)/sizeof(iw_handler), + .num_private_args = (__u16)sizeof(rP2PIwPrivTable)/sizeof(struct iw_priv_args), + .standard = rP2PIwStandardHandler, + .private = rP2PIwPrivHandler, + .private_args = rP2PIwPrivTable, +#if CFG_SUPPORT_P2P_RSSI_QUERY + .get_wireless_stats = mtk_p2p_wext_get_wireless_stats, +#else + .get_wireless_stats = NULL, +#endif +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* for IE Searching */ +extern BOOLEAN +wextSrchDesiredWPAIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); +#endif + +/* Net Device Hooks */ +static int +p2pOpen( + IN struct net_device *prDev + ); + +static int +p2pStop( + IN struct net_device *prDev + ); + +static struct net_device_stats * +p2pGetStats ( + IN struct net_device *prDev + ); + +static void +p2pSetMulticastList( + IN struct net_device *prDev + ); + +static int +p2pHardStartXmit( + IN struct sk_buff *prSkb, + IN struct net_device *prDev + ); + +static int +p2pDoIOCTL( + struct net_device *prDev, + struct ifreq *prIFReq, + int i4Cmd + ); + +static int +p2pSetMACAddress( + IN struct net_device *prDev, + void *addr + ); + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Override the implementation of select queue +* +* \param[in] dev Pointer to struct net_device +* \param[in] skb Pointer to struct skb_buff +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +unsigned int _p2p_cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp = 0; + + /* skb->priority values from 256->263 are magic values + * directly indicate a specific 802.1d priority. This is + * to allow 802.1d priority to be passed directly in from + * tags + */ + + if (skb->priority >= 256 && skb->priority <= 263) { + return skb->priority - 256; + } + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + } + return dscp >> 5; +} + + +static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +static UINT_16 +p2pSelectQueue( + struct net_device *dev, + struct sk_buff *skb) +{ + skb->priority = _p2p_cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} + +static struct net_device *g_P2pPrDev; + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int +p2pInit( + struct net_device *prDev + ) +{ + if (!prDev) { + return -ENXIO; + } + + return 0; /* success */ +} /* end of p2pInit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void +p2pUninit ( + IN struct net_device *prDev + ) +{ + + + return; +} /* end of p2pUninit() */ + + + + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) +static const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + .ndo_set_rx_mode = p2pSetMulticastList, +#else + .ndo_set_multicast_list = p2pSetMulticastList, +#endif + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + .ndo_select_queue = p2pSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + + +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2PAllocInfo ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_WIFI_VAR_T prWifiVar = NULL; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + ASSERT(prAdapter); + ASSERT(prWifiVar); + + do { + if (prGlueInfo == NULL) { + break; + } + + if (prGlueInfo->prP2PInfo == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo = + kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); + prAdapter->prP2pInfo = + kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2PConnSettings = + kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T),VIR_MEM_TYPE); + prWifiVar->prP2pFsmInfo = + kalMemAlloc(sizeof(P2P_FSM_INFO_T),VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo = + kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T),VIR_MEM_TYPE); + } + else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings != NULL); + ASSERT(prWifiVar->prP2pFsmInfo != NULL); + ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL); + } + /*MUST set memory to 0 */ + kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T)); + kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T)); + kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T)); + kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); + kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + } while (FALSE); + + + /* chk if alloc successful or not*/ + if (prGlueInfo->prP2PInfo && + prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings && + prWifiVar->prP2pFsmInfo && + prWifiVar->prP2pSpecificBssInfo) { + return TRUE; + } + else { + + if (prWifiVar->prP2pSpecificBssInfo) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prWifiVar->prP2pSpecificBssInfo = NULL; + } + if (prWifiVar->prP2pFsmInfo) { + kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + + prWifiVar->prP2pFsmInfo = NULL; + } + if (prWifiVar->prP2PConnSettings) { + kalMemFree(prWifiVar->prP2PConnSettings, VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); + + prWifiVar->prP2PConnSettings = NULL; + } + if (prGlueInfo->prP2PInfo) { + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + + prGlueInfo->prP2PInfo = NULL; + } + if (prAdapter->prP2pInfo) { + kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + + prAdapter->prP2pInfo = NULL; + } + return FALSE; + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2PFreeInfo( + P_GLUE_INFO_T prGlueInfo + ) +{ + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + + /* free memory after p2p module is ALREADY unregistered */ + if(prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + + kalMemFree(prGlueInfo->prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings, VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + /*Reomve p2p bss scan list*/ + scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter); + + /*reset all pointer to NULL */ + prGlueInfo->prP2PInfo = NULL; + prGlueInfo->prAdapter->prP2pInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo = NULL; + + return TRUE; + } + else { + return FALSE; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enable Channel for cfg80211 for Wi-Fi Direct based on current country code +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pEnableChannel( + PUINT_8 pucChIdx, + UINT_8 ucChannelNum, + struct ieee80211_channel *mtk_channels, + UINT_8 mtk_channel_sz +) +{ + UINT_8 ucCurChIdx = *pucChIdx; + + while(TRUE) { + (*pucChIdx)++; + (*pucChIdx) %= mtk_channel_sz; + + if(ucChannelNum == mtk_channels[*pucChIdx].hw_value) { + mtk_channels[*pucChIdx].flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + + if(*pucChIdx == ucCurChIdx) { + printk(KERN_ALERT DRV_NAME "Orphan channel [%d]\n", ucChannelNum); + break; + } + } +} + + +BOOLEAN +p2pNetRegister( + P_GLUE_INFO_T prGlueInfo, + BOOLEAN fgIsRtnlLockAcquired + ) +{ + BOOLEAN fgDoRegister = FALSE; + BOOLEAN fgRollbackRtnlLock = FALSE; + BOOLEAN ret; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if(prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERING; + fgDoRegister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if(!fgDoRegister) { + return TRUE; + } + + if(fgIsRtnlLockAcquired && rtnl_is_locked()) { + fgRollbackRtnlLock = TRUE; + rtnl_unlock(); + } + + /* Here are functions which need rtnl_lock */ + wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy); + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { + printk(KERN_ALERT DRV_NAME "unable to register netdevice for p2p\n"); + + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + + ret = FALSE; + } + else { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + ret = TRUE; + } + + if(fgRollbackRtnlLock) { + rtnl_lock(); + } + + return ret; +} + +BOOLEAN +p2pNetUnregister( + P_GLUE_INFO_T prGlueInfo, + BOOLEAN fgIsRtnlLockAcquired + ) +{ + BOOLEAN fgDoUnregister = FALSE; + BOOLEAN fgRollbackRtnlLock = FALSE; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if(prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; + fgDoUnregister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if(!fgDoUnregister) { + return TRUE; + } + + /* prepare for removal */ + if(netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) { + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + } + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + if(fgIsRtnlLockAcquired && rtnl_is_locked()) { + fgRollbackRtnlLock = TRUE; + rtnl_unlock(); + } + /* Here are functions which need rtnl_lock */ + + unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler); + + wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy); + + if(fgRollbackRtnlLock) { + rtnl_lock(); + } + + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pUpdateChannelTableByDomain( + P_GLUE_INFO_T prGlueInfo + ) +{ + UINT_8 i, uc2gChIdx, uc5gChIdx; + UINT_8 ucMaxChannelNum = ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_a_channels); + UINT_8 ucNumOfChannel = ucMaxChannelNum; + RF_CHANNEL_INFO_T aucChannelList[ucMaxChannelNum]; + + uc2gChIdx = uc5gChIdx = 0; + + // 1. Disable all channel + for(i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + } + for(i = 0; i < ARRAY_SIZE(mtk_5ghz_a_channels); i++) { + mtk_5ghz_a_channels[i].flags |= IEEE80211_CHAN_DISABLED; + } + + // 2. Get current domain channel list + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_NULL, ucMaxChannelNum, &ucNumOfChannel, aucChannelList); + + // 3. Enable specific channel based on domain channel list + for(i = 0; i < ucNumOfChannel; i++) { + switch(aucChannelList[i].eBand) { + case BAND_2G4: + p2pEnableChannel(&uc2gChIdx, aucChannelList[i].ucChannelNum, mtk_2ghz_channels, ARRAY_SIZE(mtk_2ghz_channels)); + break; + + case BAND_5G: + p2pEnableChannel(&uc5gChIdx, aucChannelList[i].ucChannelNum, mtk_5ghz_a_channels, ARRAY_SIZE(mtk_5ghz_a_channels)); + break; + + default: + printk(KERN_ALERT DRV_NAME "Unknow band.\n"); + break; + + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for cfg80211 for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +glRegisterP2P( + P_GLUE_INFO_T prGlueInfo, + const char *prDevName, + BOOLEAN fgIsApMode + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GL_HIF_INFO_T prHif = NULL; + PARAM_MAC_ADDRESS rMacAddr; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + printk("glRegisterP2P\n"); + + /*0. allocate p2pinfo */ + if(!p2PAllocInfo(prGlueInfo)) { + printk(KERN_ALERT DRV_NAME "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* 1. allocate WIPHY */ + prGlueInfo->prP2PInfo->wdev.wiphy = wiphy_new(&mtk_p2p_config_ops, sizeof(P_GLUE_INFO_T)); + if (!prGlueInfo->prP2PInfo->wdev.wiphy) { + printk(KERN_ALERT DRV_NAME "unable to allocate wiphy for p2p\n"); + + goto err_alloc_wiphy; + } + + /* 1.1 fill wiphy parameters */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev); + if(!prDev) { + printk(KERN_ALERT DRV_NAME "unable to get struct dev for p2p\n"); + } +#else + prDev = &(prHif->func->dev); +#endif + set_wiphy_dev(prGlueInfo->prP2PInfo->wdev.wiphy, prDev); + + prGlueInfo->prP2PInfo->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_STATION); + + p2pUpdateChannelTableByDomain(prGlueInfo); + prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz; + if(prAdapter->fgEnable5GBand) { + prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + } + + prGlueInfo->prP2PInfo->wdev.wiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prGlueInfo->prP2PInfo->wdev.wiphy->max_remain_on_channel_duration = 5000; + prGlueInfo->prP2PInfo->wdev.wiphy->n_cipher_suites = 5; + prGlueInfo->prP2PInfo->wdev.wiphy->cipher_suites = (const u32*)cipher_suites; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) + prGlueInfo->prP2PInfo->wdev.wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; +#else + prGlueInfo->prP2PInfo->wdev.wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) + prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prGlueInfo->prP2PInfo->wdev.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +#endif + +#if 0 + /* 2. Register WIPHY */ + if(wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy) < 0) { + printk(KERN_ALERT DRV_NAME "Couldn't register wiphy device for p2p\n"); + + goto err_reg_wiphy; + } +#endif + + /* 2.1 set priv as pointer to glue structure */ + *((P_GLUE_INFO_T *) wiphy_priv(prGlueInfo->prP2PInfo->wdev.wiphy)) = prGlueInfo; + + /* 2.2 wdev initialization */ + if(fgIsApMode) { + prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_AP; + } else { + prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; + } + +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + /* 3. allocate netdev */ + prGlueInfo->prP2PInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM); + if (!prGlueInfo->prP2PInfo->prDevHandler) { + printk(KERN_ALERT DRV_NAME "unable to allocate netdevice for p2p\n"); + + printk("unable to allocate netdevice for p2p\n"); + + goto err_alloc_netdev; + } + + /* 4. setup netdev */ + /* 4.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] ^= 0x2; // change to local administrated address + memcpy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + memcpy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr, prGlueInfo->prP2PInfo->prDevHandler->dev_addr, ETH_ALEN); + + /* 4.3 register callback functions */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) + prGlueInfo->prP2PInfo->prDevHandler->netdev_ops = &p2p_netdev_ops; +#else + prGlueInfo->prP2PInfo->prDevHandler->open = p2pOpen; + prGlueInfo->prP2PInfo->prDevHandler->stop = p2pStop; + prGlueInfo->prP2PInfo->prDevHandler->get_stats = p2pGetStats; + prGlueInfo->prP2PInfo->prDevHandler->set_multicast_list = p2pSetMulticastList; + prGlueInfo->prP2PInfo->prDevHandler->hard_start_xmit = p2pHardStartXmit; + prGlueInfo->prP2PInfo->prDevHandler->do_ioctl = p2pDoIOCTL; + prGlueInfo->prP2PInfo->prDevHandler->set_mac_address = p2pSetMACAddress; +#endif +// prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; + + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->prP2PInfo->prDevHandler, &(prHif->func->dev)); +#endif + + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prGlueInfo->prP2PInfo->prDevHandler->ieee80211_ptr = &(prGlueInfo->prP2PInfo->wdev); + prGlueInfo->prP2PInfo->wdev.netdev = prGlueInfo->prP2PInfo->prDevHandler; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prGlueInfo->prP2PInfo->prDevHandler->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +#if 0 + /* 7. net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* 8. register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { + printk(KERN_ALERT DRV_NAME "unable to register netdevice for p2p\n"); + + goto err_reg_netdev; + } +#endif + + /* 8. set p2p net device register state */ + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + /* 9. setup running mode*/ + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode; + + /* 10. finish */ + p2pFsmInit(prAdapter); + + p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings); + + /* Active network too early would cause HW not able to sleep. + * Defer the network active time. + */ +// nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + return TRUE; +#if 0 +err_reg_netdev: + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); +#endif +err_alloc_netdev: +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +// wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy); + +//err_reg_wiphy: + wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy); + prGlueInfo->prP2PInfo->wdev.wiphy = NULL; + +err_alloc_wiphy: +#endif + + return FALSE; +} /* end of glRegisterP2P() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister Net Device for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +glUnregisterP2P( + P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + p2pFsmUninit(prGlueInfo->prAdapter); + + nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + +#if 0 + /* Release command, mgmt and security frame belong to P2P network in + * prGlueInfo->prCmdQue + * prAdapter->rPendingCmdQueue + * prAdapter->rTxCtrl.rTxMgmtTxingQueue + * To ensure there is no pending CmdDone/TxDone handler to be executed after p2p module is removed. + */ + + /* Clear CmdQue*/ + kalClearMgmtFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + kalClearSecurityFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingCmdQue*/ + wlanReleasePendingCMDbyNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); +#endif + +#if 0 + /* prepare for removal */ + if(netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) { + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + } + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler); +#endif + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + prGlueInfo->prP2PInfo->prDevHandler = NULL; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if 0 + wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy); +#endif + wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy); + prGlueInfo->prP2PInfo->wdev.wiphy = NULL; +#endif + + /* Free p2p memory */ +#if 1 + if(!p2PFreeInfo(prGlueInfo)) { + printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#endif + return TRUE; + +} /* end of glUnregisterP2P() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for stop p2p fsm immediate + * + * \param[in] prGlueInfo Pointer to struct P_GLUE_INFO_T. + * + * \retval TRUE The execution succeeds. + * \retval FALSE The execution failed. + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pStopImmediate( + P_GLUE_INFO_T prGlueInfo + ) +{ +// P_ADAPTER_T prAdapter = NULL; +// P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; + + ASSERT(prGlueInfo); + +// prAdapter = prGlueInfo->prAdapter; +// ASSERT(prAdapter); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + +#if 0 + /* 2. switch P2P-FSM off */ + /* 2.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); // Can't trigger P2P FSM + printk(KERN_ALERT DRV_NAME "Allocate for p2p mesasage FAILED\n"); + //return -ENOMEM; + } + + /* 2.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = FALSE; + + /* 2.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prFuncSwitch, + MSG_SEND_METHOD_UNBUF); + +#endif + + /* 3. stop queue and turn off carrier */ + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; + + return TRUE; +} /* end of p2pStop() */ + + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int +p2pOpen( + IN struct net_device *prDev + ) +{ +// P_GLUE_INFO_T prGlueInfo = NULL; +// P_ADAPTER_T prAdapter = NULL; +// P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; + + ASSERT(prDev); + +#if 0 // Move after device name set. (mtk_p2p_set_local_dev_info) + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. switch P2P-FSM on */ + /* 1.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + /* 1.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = TRUE; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + + /* 2. carrier on & start TX queue */ + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of p2pOpen() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int +p2pStop( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + // P_ADAPTER_T prAdapter = NULL; +// P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + + struct cfg80211_scan_request *prScanRequest = NULL; + GLUE_SPIN_LOCK_DECLARATION(); + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + ASSERT(prGlueP2pInfo); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if(prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if(prScanRequest) { + cfg80211_scan_done(prScanRequest, TRUE); + } + +#if 0 + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); + + /* 2. switch P2P-FSM off */ + /* 2.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + /* 2.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = FALSE; + + /* 2.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + /* 3. stop queue and turn off carrier */ + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; + + netif_tx_stop_all_queues(prDev); + if(netif_carrier_ok(prDev)) { + netif_carrier_off(prDev); + } + + return 0; +} /* end of p2pStop() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to get the network interface statistical + * information. + * + * Whenever an application needs to get statistics for the interface, this method + * is called. This happens, for example, when ifconfig or netstat -i is run. + * + * \param[in] prDev Pointer to struct net_device. + * + * \return net_device_stats buffer pointer. + */ +/*----------------------------------------------------------------------------*/ +struct net_device_stats * +p2pGetStats ( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + +#if 0 // frog temp fix + //@FIXME + //prDev->stats.rx_packets = 0; + //prDev->stats.tx_packets = 0; + prDev->stats.tx_errors = 0; + prDev->stats.rx_errors = 0; + //prDev->stats.rx_bytes = 0; + //prDev->stats.tx_bytes = 0; + prDev->stats.multicast = 0; + + return &prDev->stats; + +#else + //prGlueInfo->prP2PInfo->rNetDevStats.rx_packets = 0; + //prGlueInfo->prP2PInfo->rNetDevStats.tx_packets = 0; + prGlueInfo->prP2PInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; + //prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes = 0; + //prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes = 0; + //prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; + prGlueInfo->prP2PInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->prP2PInfo->rNetDevStats; +#endif +} /* end of p2pGetStats() */ + + + + +static void +p2pSetMulticastList ( + IN struct net_device *prDev + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + printk(KERN_WARNING DRV_NAME" abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + + g_P2pPrDev = prDev; + + //4 Mark HALT, notify main thread to finish current job + prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_MULTICAST; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + +} /* p2pSetMulticastList */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to set multicast list and set rx mode. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +mtk_p2p_wext_set_Multicastlist ( + P_GLUE_INFO_T prGlueInfo + ) +{ + UINT_32 u4SetInfoLen = 0; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + printk(KERN_WARNING DRV_NAME" abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + + if (prDev->flags & IFF_PROMISC) { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + } + + if (prDev->flags & IFF_BROADCAST) { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + } + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { +#else + (prDev->mc_count > MAX_NUM_GROUP_ADDR)) { +#endif + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } + else { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + struct netdev_hw_addr *ha; +#else + struct dev_mc_list *prMcList; +#endif + UINT_32 i = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + netdev_for_each_mc_addr(ha, prDev) { + if(i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr); + i++; + } + } +#else + for (i = 0, prMcList = prDev->mc_list; + (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR); + i++, prMcList = prMcList->next) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), prMcList->dmi_addr); + } +#endif + + DBGLOG(P2P, TRACE, ("SEt Multicast Address List\n")); + + if (i >= MAX_NUM_GROUP_ADDR) { + return; + } + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PInfo->aucMCAddrList[0]), + (i * ETH_ALEN), + &u4SetInfoLen); + + } + + return; +} /* end of p2pSetMulticastList() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * * \brief This function is TX entry point of NET DEVICE. + * * + * * \param[in] prSkb Pointer of the sk_buff to be sent + * * \param[in] prDev Pointer to struct net_device + * * + * * \retval NETDEV_TX_OK - on success. + * * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + * */ +/*----------------------------------------------------------------------------*/ +int +p2pHardStartXmit( + IN struct sk_buff *prSkb, + IN struct net_device *prDev + ) +{ + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_16 u2QueueIdx = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + // mark as P2P packets + GLUE_SET_PKT_FLAG_P2P(prSkb); + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + printk(KERN_INFO DRV_NAME"Incorrect queue index, skip this frame\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + netif_stop_subqueue(prDev, u2QueueIdx); + } + } + else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + + /* Statistic usage. */ + prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.tx_packets++; + //prDev->stats.tx_packets++; + + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIFReq Our private ioctl request structure, typed for the generic + * struct ifreq so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval WLAN_STATUS_SUCCESS The IOCTL command is executed successfully. + * \retval OTHER The execution of IOCTL command is failed. + */ +/*----------------------------------------------------------------------------*/ +int +p2pDoIOCTL( + struct net_device *prDev, + struct ifreq *prIFReq, + int i4Cmd + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + struct iwreq *prIwReq = (struct iwreq *)prIFReq; + struct iw_request_info rIwReqInfo; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (prGlueInfo->u4ReadyFlag == 0) { + // adapter not ready yet + return -EINVAL; + } + + // fill rIwReqInfo + rIwReqInfo.cmd = (__u16)i4Cmd; + rIwReqInfo.flags = 0; + + switch(i4Cmd) { + case SIOCSIWENCODEEXT: + /* Set Encryption Material after 4-way handshaking is done */ + if (prIwReq->u.encoding.pointer) { + u4ExtraSize = prIwReq->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + prIwReq->u.encoding.pointer, + prIwReq->u.encoding.length)) { + ret = -EFAULT; + } + } + else if (prIwReq->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if(ret == 0) { + ret = mtk_p2p_wext_set_key(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + break; + + case SIOCSIWMLME: + /* IW_MLME_DISASSOC used for disconnection*/ + if (prIwReq->u.data.length != sizeof(struct iw_mlme)) { + printk(KERN_INFO "MLME buffer strange:%d\n", prIwReq->u.data.length); + ret = -EINVAL; + break; + } + + if (!prIwReq->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = - ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, prIwReq->u.data.pointer, sizeof(struct iw_mlme))) { + ret = -EFAULT; + } + else { + ret = mtk_p2p_wext_mlme_handler(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + case SIOCGIWPRIV: + /* This ioctl is used to list all IW privilege ioctls */ + ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCGIWSCAN: + ret = mtk_p2p_wext_discovery_results(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCSIWAUTH: + ret = mtk_p2p_wext_set_auth(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case IOC_P2P_CFG_DEVICE: + case IOC_P2P_PROVISION_COMPLETE: + case IOC_P2P_START_STOP_DISCOVERY: + case IOC_P2P_DISCOVERY_RESULTS: + case IOC_P2P_WSC_BEACON_PROBE_RSP_IE: + case IOC_P2P_CONNECT_DISCONNECT: + case IOC_P2P_PASSWORD_READY: + case IOC_P2P_GET_STRUCT: + case IOC_P2P_SET_STRUCT: + case IOC_P2P_GET_REQ_DEVICE_INFO: + ret = rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV](prDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); + break; +#if CFG_SUPPORT_P2P_RSSI_QUERY + case SIOCGIWSTATS: + ret = mtk_p2p_wext_get_rssi(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; +#endif + default: + ret = -ENOTTY; + } + + return ret; +} /* end of p2pDoIOCTL() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the private supported IOCTLs table to user space. + * + * \param[in] prDev Net device requested. + * \param[out] prIfReq Pointer to ifreq structure, content is copied back to + * user space buffer in gl_iwpriv_table. + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_priv ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + struct iw_point *prData= (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = 0; + + ASSERT(prDev); + + u2BufferSize = prData->length; + + /* update our private table size */ + prData->length = (__u16)sizeof(rP2PIwPrivTable)/sizeof(struct iw_priv_args); + + if (u2BufferSize < prData->length) { + return -E2BIG; + } + + if (prData->length) { + if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) { + return -EFAULT; + } + } + + return 0; +} /* end of mtk_p2p_wext_get_priv() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate P2P-FSM for re-associate to the connecting device + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 For success. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_reconnect ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + /* 1.2 fill message */ + + DBGLOG(P2P, TRACE, ("mtk_p2p_wext_reconnect: P2P Reconnect\n")); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgHdr, + MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_reconnect() */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief MLME command handler +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_mlme_handler( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T)NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T)NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, ("mtk_p2p_wext_mlme_handler:\n")); + + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + if (!prMsgP2PConnAbt) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data); + + prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code; + + + if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) { + DBGLOG(P2P, TRACE, ("P2P Connection Abort:\n")); + + /* 1.2 fill message */ + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + } + else { + DBGLOG(P2P, TRACE, ("P2P Connection Pause:\n")); + + /* 1.2 fill message */ + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgP2PConnAbt, + MSG_SEND_METHOD_BUF); + + break; + + default: + return -EOPNOTSUPP; + } +#endif + return 0; +} /* end of mtk_p2p_wext_mlme_handler() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_provision_complete( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData= (struct iw_point *)&wrqu->data; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + switch(prData->flags) { + case P2P_PROVISIONING_SUCCESS: + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + /* 1.2 fill message */ + + prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgHdr, + MSG_SEND_METHOD_BUF); + + break; + + case P2P_PROVISIONING_FAIL: + + break; + + default: + return -EOPNOTSUPP; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_set_provision_complete() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_stop_discovery( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData= (struct iw_point *)&wrqu->data; + P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra; + UINT_8 au4IeBuf[MAX_IE_LENGTH]; + P_MSG_HDR_T prMsgHdr; + P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if(prData->flags == P2P_STOP_DISCOVERY) { + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_HDR_T)); + + if (!prMsgHdr) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgHdr, + MSG_SEND_METHOD_BUF); + } + else if(prData->flags == P2P_START_DISCOVERY) { + + /* retrieve IE for Probe Response */ + if(prReqDeviceType->probe_rsp_len > 0) { + if(prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) { + if(copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[2], prReqDeviceType->probe_rsp_ie, prReqDeviceType->probe_rsp_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prReqDeviceType->probe_rsp_len; + } + else { + return -E2BIG; + } + } + + /* retrieve IE for Probe Request */ + if(prReqDeviceType->probe_req_len > 0) { + if(prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) { + if(copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[1], prReqDeviceType->probe_req_ie, prReqDeviceType->probe_req_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prReqDeviceType->probe_req_len; + } + else { + return -E2BIG; + } + } + /* update IE for Probe Request */ + + if(prReqDeviceType->scan_type == P2P_LISTEN) { + /* update listening parameter */ + + /* @TODO: update prConnSettings for Probe Response IE */ + } + else { + // indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY + prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_DEVICE_DISCOVER_T)); + + if (!prDiscoverMsg) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prDiscoverMsg->u4DevDiscoverTime = 0; // unlimited + prDiscoverMsg->fgIsSpecificType = TRUE; + prDiscoverMsg->rTargetDeviceType.u2CategoryID = *(PUINT_16)(&(prReqDeviceType->pri_device_type[0])); + prDiscoverMsg->rTargetDeviceType.u2SubCategoryID = *(PUINT_16)(&(prReqDeviceType->pri_device_type[6]));; + COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr); + + /* @FIXME: parameter to be refined, where to pass IE buffer ? */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prDiscoverMsg, + MSG_SEND_METHOD_BUF); + } + } + else { + return -EINVAL; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_start_stop_discovery() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T)NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + struct iw_point *prData = (struct iw_point*)&wrqu->data; + P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT)NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT)extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + + if (prIoctlInvitation->ucReinvoke == 1) { + // TODO: Set Group ID + p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID, prIoctlInvitation->aucSsid, prIoctlInvitation->u4SsidLen); + } + + else { + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T)NULL; + + // TODO: Do Invitation. + prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_INVITATION_REQUEST_T)); + if (!prMsgP2PInvitationReq) { + ASSERT(0); // Can't trigger P2P FSM + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationReq->aucDeviceID, prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, ("mtk_p2p_wext_invitation_request: P2P Invitation Req\n")); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgP2PInvitationReq, + MSG_SEND_METHOD_BUF); + + } + + + + } while (FALSE); +#endif + + return i4Status; + +} +/* mtk_p2p_wext_invitation_request */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_abort ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T)NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + struct iw_point *prData = (struct iw_point*)&wrqu->data; + P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION)NULL; + + UINT_8 bssid[MAC_ADDR_LEN]; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION)extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + else { + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationAbort = (P_MSG_P2P_INVITATION_REQUEST_T)NULL; + + prMsgP2PInvitationAbort = (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_INVITATION_REQUEST_T)); + + if (!prMsgP2PInvitationAbort) { + ASSERT(0); // Can't trigger P2P FSM + i4Status = -ENOMEM; + break; + } + + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationAbort->aucDeviceID, prIoctlInvitationAbort->dev_addr, MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, ("mtk_p2p_wext_invitation_request: P2P Invitation Req\n")); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgP2PInvitationAbort, + MSG_SEND_METHOD_BUF); + + } + + + } while (FALSE); +#endif + + return i4Status; + +} +/* mtk_p2p_wext_invitation_abort */ + + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To override p2p interface address + * + * \param[in] prDev Net device requested. + * \param[in] addr Pointer to address + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +p2pSetMACAddress( + IN struct net_device *prDev, + void *addr + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + //@FIXME + return eth_mac_addr(prDev, addr); +} + + + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher suite +* +* \param[in] prDev Net device requested. +* \param[out] +* +* \retval 0 Success. +* \retval -EINVAL Invalid parameter +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_auth ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_param *prAuth = (struct iw_param *)wrqu; + + ASSERT(prDev); + ASSERT(prAuth); + if (FALSE == GLUE_CHK_PR2(prDev, prAuth)) { + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + /* Save information to glue info and process later when ssid is set. */ + switch(prAuth->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + break; + case IW_AUTH_CIPHER_PAIRWISE: + prGlueInfo->prP2PInfo->u4CipherPairwise = prAuth->value; + break; + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + //@TODO + break; + } + + return 0; +} /* end of mtk_p2p_wext_set_auth() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[out] prIfReq Pointer to ifreq structure, content is copied back to +* user space buffer in gl_iwpriv_table. +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_key( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int ret = 0; + struct iw_encode_ext *prIWEncExt; + struct iw_point *prEnc; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + UINT_8 keyStructBuf[100]; + P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; + P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + do { + if (wrqu->encoding.pointer) { + u4ExtraSize = wrqu->encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + wrqu->encoding.pointer, + wrqu->encoding.length)) { + ret = -EFAULT; + break; + } + } + else if (wrqu->encoding.length != 0) { + ret = -EINVAL; + break; + } + + prEnc = &wrqu->encoding; + prIWEncExt = (struct iw_encode_ext *) prExtraBuf; + + if (GLUE_CHK_PR3(prDev, prEnc, prExtraBuf) == TRUE) { + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { // Key Removal + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + prRemoveKey, + prRemoveKey->u4Length, + FALSE, + FALSE, + TRUE, + TRUE, + &u4BufLen); + + if(rStatus != WLAN_STATUS_SUCCESS) + ret = -EFAULT; + } + else { + if(prIWEncExt->alg == IW_ENCODE_ALG_CCMP) { + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + ((prEnc->flags & IW_ENCODE_INDEX) - 1) : 0; + if (prKey->u4KeyIndex <= 3) { + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31)*/ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prKey->u4KeyIndex |= 0x1UL << 31; + } + + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + } + else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((UINT_32)&(((P_PARAM_KEY_T)0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddP2PKey, + prKey, + prKey->u4Length, + FALSE, + FALSE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + ret = -EFAULT; + } + } + else { + ret = -EINVAL; + } + } + else { + ret = -EINVAL; + } + } + } + else + ret = -EINVAL; + + } while(FALSE); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + + return ret; +} /* end of mtk_p2p_wext_set_key() */ + + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_powermode( + IN struct net_device *prNetDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + //printk("set_powermode = %d, value = %d\n", wrqu->power.disabled, wrqu->power.value); + struct iw_param *prPower = (struct iw_param*)&wrqu->power; +#if 1 + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + //printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", + // prPower->value, prPower->disabled, prPower->flags); + + if(prPower->disabled){ + ePowerMode = Param_PowerModeCAM; + } + else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + else { + printk(KERN_DEBUG "%s(): unsupported power management mode value = %d.\n", + __FUNCTION__, + prPower->value); + + return -EINVAL; + } + } + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + FALSE, + FALSE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); + return -EFAULT; + } + +#endif + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief get the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_powermode( + IN struct net_device *prNetDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + //printk("mtk_p2p_wext_get_powermode\n"); + //wrqu->power.disabled = 0; + //wrqu->power.value = 1; + + struct iw_param *prPower = (struct iw_param*)&wrqu->power; + PARAM_POWER_MODE ePowerMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) { + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + +#if 1 + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pPowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + TRUE, + FALSE, + FALSE, + TRUE, + &u4BufLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryP2pPowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + &u4BufLen); +#endif + + prPower->value = 0; + prPower->disabled = 1; + + if (Param_PowerModeCAM == ePowerMode) { + prPower->value = 0; + prPower->disabled = 1; + } + else if (Param_PowerModeMAX_PSP == ePowerMode ) { + prPower->value = 1; + prPower->disabled = 0; + } + else if (Param_PowerModeFast_PSP == ePowerMode ) { + prPower->value = 2; + prPower->disabled = 0; + } + + prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; +#if WIRELESS_EXT < 21 + prPower->value *= 1000000; +#endif + + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_CFG_DEVICE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_local_dev_info( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_CFG_DEVICE_TYPE prDeviceCfg = (P_IW_P2P_CFG_DEVICE_TYPE) extra; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + //P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + // update connection settings for P2P-FSM + // 1. update SSID + if(prDeviceCfg->ssid_len > ELEM_MAX_LEN_SSID) { + prConnSettings->ucSSIDLen = ELEM_MAX_LEN_SSID; + } + else { + prConnSettings->ucSSIDLen = prDeviceCfg->ssid_len; + } + + if(copy_from_user(prConnSettings->aucSSID, prDeviceCfg->ssid, prConnSettings->ucSSIDLen)) { + return -EFAULT; + } + + // 2. update device type (WPS IE) + kalMemCopy(&(prConnSettings->rPrimaryDevTypeBE), &(prDeviceCfg->pri_device_type), sizeof(DEVICE_TYPE_T)); +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + kalMemCopy(&(prConnSettings->arSecondaryDevTypeBE[0]), &(prDeviceCfg->snd_device_type), sizeof(DEVICE_TYPE_T)); +#endif + + // 3. update device name + if(prDeviceCfg->device_name_len > WPS_ATTRI_MAX_LEN_DEVICE_NAME) { + prConnSettings->ucDevNameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + } + else { + prConnSettings->ucDevNameLen = prDeviceCfg->device_name_len; + } + if(copy_from_user(prConnSettings->aucDevName, prDeviceCfg->device_name, prConnSettings->ucDevNameLen)) { + return -EFAULT; + } + + // 4. update GO intent + prConnSettings->ucGoIntent = prDeviceCfg->intend; + + + /* Preferred channel bandwidth */ + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = + prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = + prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; + +#if 0 + /* 1. switch P2P-FSM on */ + /* 1.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + /* 1.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = TRUE; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_set_local_dev_info() */ + + + + + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief I/O Control handler for both + * IOC_P2P_START_STOP_DISCOVERY & SIOCGIWSCAN + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 Success. + * \retval -EFAULT Setting parameters to driver fail. + * \retval -EOPNOTSUPP Key size not supported. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_discovery_results( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + struct iw_event iwe; + char *current_ev = extra; + UINT_32 i; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_P2P_INFO_T prP2PInfo = (P_P2P_INFO_T)NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T)NULL; + P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2PInfo = prAdapter->prP2pInfo; + + for(i = 0 ; i < prP2PInfo->u4DeviceNum ; i++) { + prTargetResult = &prP2PInfo->arP2pDiscoverResult[i]; + + /* SIOCGIWAP */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, + prTargetResult->aucInterfaceAddr, + 6); + + current_ev = iwe_stream_add_event(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, IW_EV_ADDR_LEN); + + + /* SIOCGIWESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + iwe.u.data.length = prTargetResult->u2NameLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, prTargetResult->aucName); + + /* IWEVGENIE for WPA IE */ + if(prTargetResult->u2IELength <= 600 && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)prDesiredIE); + } + +#if CFG_SUPPORT_WPS + + /* IWEVGENIE for WPS IE */ + if((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPSIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)prDesiredIE); + } + +#endif + + /* IWEVGENIE for RSN IE */ + if((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0x30, + (PUINT_8 *)&prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)prDesiredIE); + } + + /* IOC_P2P_GO_WSC_IE */ +#if 1 + /* device capability */ + if (1) { + UINT_8 data[40]; + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 8 + sizeof("p2p_cap="); + + snprintf(data, iwe.u.data.length, "p2p_cap=%02x%02x%02x%02x%c", + prTargetResult->ucDeviceCapabilityBitmap, prTargetResult->ucGroupCapabilityBitmap, + (UINT_8)prTargetResult->u2ConfigMethod, (UINT_8)(prTargetResult->u2ConfigMethod >> 8), '\0' ); + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)data); + + //printk("%s\n", data); + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 12 + sizeof("p2p_dev_type="); + + snprintf(data, iwe.u.data.length, "p2p_dev_type=%02x%02x%02x%02x%02x%02x%c", + (UINT_8)prTargetResult->rPriDevType.u2CategoryID,(UINT_8)prTargetResult->rPriDevType.u2SubCategoryID, + (UINT_8)prTargetResult->arSecDevType[0].u2CategoryID,(UINT_8)prTargetResult->arSecDevType[0].u2SubCategoryID, + (UINT_8)prTargetResult->arSecDevType[1].u2CategoryID,(UINT_8)prTargetResult->arSecDevType[1].u2SubCategoryID, + '\0'); + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)data); + //printk("%s\n", data); + + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 17 + sizeof("p2p_grp_bssid="); + + snprintf(data, iwe.u.data.length, "p2p_grp_bssid="MACSTR"%c", + MAC2STR(prTargetResult->aucBSSID), '\0'); + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, (char *)data); + //printk("%s\n", data); + + } +#endif + } + + /* Length of data */ + wrqu->data.length = (current_ev - extra); + wrqu->data.flags = 0; + + return 0; +} /* end of mtk_p2p_wext_discovery_results() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_WSC_BEACON_PROBE_RSP_IE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_wsc_ie( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_HOSTAPD_PARAM prHostapdParam = (P_IW_P2P_HOSTAPD_PARAM)extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (prHostapdParam->len > 0) { + if (prHostapdParam->len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[0], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + if (copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[2], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + } + else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[0] = prHostapdParam->len; + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prHostapdParam->len; + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + //@TODO: send message to P2P-FSM + + return 0; +} /* end of mtk_p2p_wext_wsc_ie() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_CONNECT_DISCONNECT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_connect_disconnect( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData= (struct iw_point *)&wrqu->data; +// P_IW_P2P_CONNECT_DEVICE prConnectDevice = (P_IW_P2P_CONNECT_DEVICE)extra; +// P_MSG_HDR_T prMsgHdr; +// P_MSG_P2P_CONNECTION_REQUEST_T prMsgP2PConnReq; +// P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt; +// UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prData->flags == P2P_CONNECT) { +#if 0 + // indicate P2P-FSM with MID_MNY_P2P_CONNECTION_REQ + prMsgP2PConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (!prMsgP2PConnReq) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgP2PConnReq, + MSG_SEND_METHOD_BUF); +#endif + } + else if(prData->flags == P2P_DISCONNECT) { +#if 0 + // indicate P2P-FSM with MID_MNY_P2P_CONNECTION_ABORT + prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (!prMsgP2PConnAbt) { + ASSERT(0); // Can't trigger P2P FSM + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prConnectDevice->sta_addr); + + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgP2PConnAbt, + MSG_SEND_METHOD_BUF); +#endif + } + else { + return -EINVAL; + } + + return 0; +} /* end of mtk_p2p_wext_connect_disconnect() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PASSWORD_READY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_password_ready( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_PASSWORD_READY prPasswordReady = (P_IW_P2P_PASSWORD_READY)extra; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + /* retrieve IE for Probe Request */ + if (prPasswordReady->probe_req_len > 0) { + if (prPasswordReady->probe_req_len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[1], prPasswordReady->probe_req_ie, prPasswordReady->probe_req_len)) { + return -EFAULT; + } + } + else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prPasswordReady->probe_req_len; + + /* retrieve IE for Probe Response */ + if (prPasswordReady->probe_rsp_len > 0) { + if (prPasswordReady->probe_rsp_len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user(prGlueInfo->prP2PInfo->aucWSCIE[2], prPasswordReady->probe_rsp_ie, prPasswordReady->probe_rsp_len)) { + return -EFAULT; + } + } + else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prPasswordReady->probe_rsp_len; + + switch (prPasswordReady->active_config_method) { + case 1: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_PUSH_BUTTON; + break; + case 2: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_KEYPAD; + break; + case 3: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_DISPLAY; + break; + default: + break; + } + + prConnSettings->fgIsPasswordIDRdy = TRUE; + return 0; +} /* end of mtk_p2p_wext_password_ready() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_REQ_DEVICE_INFO) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_request_dev_info( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_DEVICE_REQ prDeviceReq = (P_IW_P2P_DEVICE_REQ)extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + // specify data length + wrqu->data.length = sizeof(IW_P2P_DEVICE_REQ); + + // copy to upper-layer supplied buffer + kalMemCopy(prDeviceReq->name, prGlueInfo->prP2PInfo->aucConnReqDevName, prGlueInfo->prP2PInfo->u4ConnReqNameLength); + prDeviceReq->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; + prDeviceReq->name[prDeviceReq->name_len]='\0'; + COPY_MAC_ADDR(prDeviceReq->device_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); + prDeviceReq->device_type = prGlueInfo->prP2PInfo->ucConnReqDevType; + prDeviceReq->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; + prDeviceReq->active_config_method = prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod; + + return 0; +} /* end of mtk_p2p_wext_request_dev_info() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_indicate( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_IOCTL_INVITATION_INDICATE prInvIndicate = (P_IW_P2P_IOCTL_INVITATION_INDICATE)extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + // specify data length + wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_INDICATE); + + // copy to upper-layer supplied buffer + kalMemCopy(prInvIndicate->dev_name, prGlueInfo->prP2PInfo->aucConnReqDevName, prGlueInfo->prP2PInfo->u4ConnReqNameLength); + kalMemCopy(prInvIndicate->group_bssid, prGlueInfo->prP2PInfo->rConnReqGroupAddr, MAC_ADDR_LEN); + prInvIndicate->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; + prInvIndicate->dev_name[prInvIndicate->name_len]='\0'; + COPY_MAC_ADDR(prInvIndicate->dev_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); + prInvIndicate->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; + prInvIndicate->operating_channel = prGlueInfo->prP2PInfo->ucOperatingChnl; + prInvIndicate->invitation_type = prGlueInfo->prP2PInfo->ucInvitationType; + + return 0; +} /* end of mtk_p2p_wext_invitation_indicate() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_status( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_IOCTL_INVITATION_STATUS prInvStatus = (P_IW_P2P_IOCTL_INVITATION_STATUS)extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + // specify data length + wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_STATUS); + + // copy to upper-layer supplied buffer + prInvStatus->status_code = prGlueInfo->prP2PInfo->u4InvStatus; + + return 0; +} /* end of mtk_p2p_wext_invitation_status() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device found +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval TRUE Success. +* \retval FALSE Failure +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalP2PIndicateFound( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_DVC_FND"); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PDVCFND event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return FALSE; +} /* end of kalP2PIndicateFound() */ + +int +mtk_p2p_wext_set_network_address ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + //@TODO: invoke wlan_p2p functions +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetP2pNetworkAddress, + prKey, + prKey->u4Length, + FALSE, + FALSE, + TRUE, + &u4BufLen); +#endif + + return 0; + +} + +int +mtk_p2p_wext_set_ps_profile ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + //@TODO: invoke wlan_p2p functions +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetP2pPowerSaveProfile, + prKey, + prKey->u4Length, + FALSE, + FALSE, + TRUE, + &u4BufLen); +#endif + + return 0; + +} + +int +mtk_p2p_wext_set_pm_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + //@TODO: invoke wlan_p2p functions +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetP2pPowerSaveProfile, + prKey, + prKey->u4Length, + FALSE, + FALSE, + TRUE, + &u4BufLen); +#endif + + return 0; + +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_formation ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int i4Status = 0; + P_ADAPTER_T prAdapter = (P_ADAPTER_T)NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; +// struct iw_point *prData = (struct iw_point*)&wrqu->data; + P_IW_P2P_IOCTL_START_FORMATION prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION)NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION)extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + + } while (FALSE); + + return i4Status; + +} +/* mtk_p2p_wext_start_formation */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_int ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 index; + INT_32 value; + PUINT_32 pu4IntBuf; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + UINT_32 u4Leng; + + ASSERT(prDev); + ASSERT(wrqu); + + //printk("mtk_p2p_wext_set_int\n"); + pu4IntBuf = (PUINT_32) extra; + + if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) { + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + + u4SubCmd = (UINT_32) wrqu->mode; + index = pu4IntBuf[1]; + value = pu4IntBuf[2]; + + printk("set parameter, u4SubCmd=%d idx=%d value=%lu\n", (INT_16)u4SubCmd, (INT_16)index, value); + + switch (u4SubCmd) { + case PRIV_CMD_INT_P2P_SET: + switch (index) { + case 0: /* Listen CH */ + { + UINT_8 ucSuggestChnl = 0; + + prP2pConnSettings->ucListenChnl = value; + + // 20110920 - frog: User configurations are placed in ConnSettings. + if (rlmFuncFindAvailableChannel(prGlueInfo->prAdapter, value, &ucSuggestChnl, TRUE, TRUE)) { + prP2pSpecificBssInfo->ucListenChannel = value; + } + else { + prP2pSpecificBssInfo->ucListenChannel = ucSuggestChnl; + } + + + break; + } + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 100: /* Oper CH */ + // 20110920 - frog: User configurations are placed in ConnSettings. + prP2pConnSettings->ucOperatingChnl = value; + break; + case 101: /* Local config Method, for P2P SDK */ + //prP2pConnSettings->u2LocalConfigMethod; + break; + case 102: /* Sigma P2p reset */ + kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); + //prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + status = mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + + break; + + default: + break; + } + break; + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_struct ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) { + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], + sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, + wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) { + printk(KERN_INFO DRV_NAME"extra buffer is valid\n"); + } + else { + printk(KERN_INFO DRV_NAME"extra 0x%p\n", extra); + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch(prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEND_SD_RESPONSE: + status = mtk_p2p_wext_send_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_SEND_SD_REQUEST: + status = mtk_p2p_wext_send_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_TERMINATE_SD_PHASE: + status = mtk_p2p_wext_terminate_service_discovery_phase(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_INVITATION_STRUCT)) { +// status = mtk_p2p_wext_invitation_request(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + } + break; + + case P2P_CMD_ID_INVITATION_ABORT: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_ABORT_INVITATION)) { +// status = mtk_p2p_wext_invitation_abort(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + } + break; + + case P2P_CMD_ID_START_FORMATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_START_FORMATION)) { + status = mtk_p2p_wext_start_formation(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + } + break; + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (wrqu->data.length > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), + wrqu->data.pointer, + wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), extra, wrqu->data.length)) { + printk(KERN_INFO DRV_NAME"extra buffer is valid\n"); + } + else { + printk(KERN_INFO DRV_NAME"extra 0x%p\n", extra); + } + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch(prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, + wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) { + printk(KERN_INFO DRV_NAME"extra buffer is valid\n"); + } + else { + printk(KERN_INFO DRV_NAME"extra 0x%p\n", extra); + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + break; + default: + status = -EOPNOTSUPP; + break; + } + + return status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_struct ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (!prDev || !wrqu) { + printk(KERN_INFO DRV_NAME "%s(): invalid param(0x%p, 0x%p)\n", + __func__, + prDev, + wrqu); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, + sizeof(IW_P2P_TRANSPORT_STRUCT))) { + printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch(prP2PReq->u4CmdId) { + case P2P_CMD_ID_GET_SD_REQUEST: + status = mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_GET_SD_RESPONSE: + status = mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION_INDICATE: + { + status = mtk_p2p_wext_invitation_indicate(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + break; + } + case P2P_CMD_ID_INVITATION_STATUS: + { + status = mtk_p2p_wext_invitation_status(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + break; + } + case P2P_CMD_ID_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + RF_CHANNEL_INFO_T aucChannelList[50]; + UINT_8 ucMaxChannelNum = 50; + PUINT_8 pucChnlList = (PUINT_8)prP2PReq->aucBuffer; + + kalGetChnlList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + prP2PReq->outBufferLength = NumOfChannel; + + for (i=0; iaucBuffer[i] = aucChannelList[i].ucChannelNum; +#else + *pucChnlList = aucChannelList[i].ucChannelNum; + pucChnlList++; +#endif + } + if(copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + NumOfChannel + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + break; + } + + case P2P_CMD_ID_GET_OP_CH: + { + prP2PReq->inBufferLength = 4; + + status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + &prP2PReq->outBufferLength); + + if (status == 0) { // WLAN_STATUS_SUCCESS + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + break; + } + + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (wrqu->data.length > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), + wrqu->data.pointer, + sizeof(IW_P2P_TRANSPORT_STRUCT))) { + printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch(prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, + sizeof(IW_P2P_TRANSPORT_STRUCT))) { + printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + + + /* Copy queried data to user. */ + if (status == 0) { // WLAN_STATUS_SUCCESS + if(copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + else { + if(copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + break; + default: + return -EOPNOTSUPP; + } + + return status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery request frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDRequest, + prP2PReq->aucBuffer, + prP2PReq->outBufferLength, + TRUE, + FALSE, + TRUE, + TRUE, + &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + prP2PReq->outBufferLength = u4QueryInfoLen; + + if(copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery response frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDResponse, + prP2PReq->aucBuffer, + prP2PReq->outBufferLength, + TRUE, + FALSE, + TRUE, + TRUE, + &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + prP2PReq->outBufferLength = u4QueryInfoLen; + + if(copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery request frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDRequest, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery response frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDResponse, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_sec_check_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSecCheckRequest, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_sec_check_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + printk("mtk_p2p_wext_get_sec_check_response\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidGetSecCheckResponse, + prP2PReq->aucBuffer, + prP2PReq->outBufferLength, + TRUE, + FALSE, + TRUE, + TRUE, + &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + prP2PReq->outBufferLength = u4QueryInfoLen; + + if(copy_to_user(wrqu->data.pointer, + prP2PReq->aucBuffer, + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + else { + return 0; + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* terminating service discovery phase +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_terminate_service_discovery_phase ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2PTerminateSDPhase, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_noa_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + //P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_PARAM_CUSTOM_NOA_PARAM_STRUC_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + printk("mtk_p2p_wext_set_noa_param\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNoaParam, + prNoaParam, //prP2PReq->aucBuffer, + sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T),//prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_oppps_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; +// P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + printk("mtk_p2p_wext_set_oppps_param\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOppPsParam, + prOppPsParam, //prP2PReq->aucBuffer, + sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T), //prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return 0; + } +} + + +int +mtk_p2p_wext_set_p2p_version ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + UINT_32 u4SetInfoLen; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSupplicantVersion, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return rStatus; + } + + +} +/* mtk_p2p_wext_set_p2p_version */ + +int +mtk_p2p_wext_get_p2p_version ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pVersion, + prP2PReq->aucBuffer, + prP2PReq->outBufferLength, + TRUE, + FALSE, + TRUE, + TRUE, + &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return rStatus; + } + + +} /* mtk_p2p_wext_get_p2p_version */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY + +int +mtk_p2p_wext_get_rssi ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + struct iw_point *prData= (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rssi; + struct iw_statistics *pStats = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + rStatus = WLAN_STATUS_FAILURE; + goto stat_out; + } + + pStats = (struct iw_statistics *) (&(prGlueInfo->rP2pIwStats)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pRssi, + &i4Rssi, + sizeof(i4Rssi), + TRUE, + TRUE, + TRUE, + TRUE, + &u4QueryInfoLen); + + u2BufferSize = prData->length; + + if (u2BufferSize < sizeof(struct iw_statistics)) { + return -E2BIG; + } + + + if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) { + rStatus = WLAN_STATUS_FAILURE; + } + + +stat_out: + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + else { + return rStatus; + } + +} /* mtk_p2p_wext_get_rssi */ + +struct iw_statistics * +mtk_p2p_wext_get_wireless_stats ( + struct net_device *prDev + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + goto stat_out; + } + + pStats = (struct iw_statistics *) (&(prGlueInfo->rP2pIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pRssi, + &i4Rssi, + sizeof(i4Rssi), + TRUE, + TRUE, + TRUE, + TRUE, + &bufLen); + +stat_out: + return pStats; +} /* mtk_p2p_wext_get_wireless_stats */ + + +#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */ + + +int +mtk_p2p_wext_set_txpow ( + IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, + IN OUT union iwreq_data *prTxPow, + IN char *pcExtra + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_ADAPTER_T prAdapter = (P_ADAPTER_T)NULL; +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; +#endif + int i4Ret = 0; + + ASSERT(prDev); + ASSERT(prTxPow); + + do { + if ((!prDev) || (!prTxPow)) { + i4Ret = -EINVAL; + break; + } + + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + + if (!prGlueInfo) { + i4Ret = -EINVAL; + break; + } + + + prAdapter = prGlueInfo->prAdapter; +#if 0 + prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(0); + return -ENOMEM; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + if (prTxPow->disabled) { + /* Dissolve. */ + prMsgFuncSwitch->fgIsFuncOn = FALSE; + } + else { + + /* Re-enable function. */ + prMsgFuncSwitch->fgIsFuncOn = TRUE; + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + + } while (FALSE); + + return i4Ret; +} /* mtk_p2p_wext_set_txpow */ + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c new file mode 100755 index 000000000000..83ce96fbf236 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,2305 @@ +/* +** $Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_cfg80211.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + using cfg80211 interface + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_p2p_cfg80211.c $ +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 09 05 2012 wh.su +** [ALPS00351547] [6577JB][WiFi direct]The 3rd device fail to establish p2p connection with GO sometimes +** sync with the ICS code. +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 08 21 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. +** +** 08 17 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** Fix p2p bug find on ALPS.JB trunk. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include + +#include "precomp.h" +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +BOOLEAN +mtk_p2p_cfg80211func_channel_format_switch( + IN struct ieee80211_channel *channel, + IN enum nl80211_channel_type channel_type, + IN P_RF_CHANNEL_INFO_T prRfChnlInfo, + IN P_ENUM_CHNL_EXT_T prChnlSco + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) +int mtk_p2p_cfg80211_add_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + struct key_params *params + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P2P_PARAM_KEY_T rKey; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&rKey, sizeof(P2P_PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + if(mac_addr) { + memcpy(rKey.arBSSID, mac_addr, ETH_ALEN); + if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && + (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + } + if (rKey.arBSSID[0] != 0xFF) { + rKey.u4KeyIndex |= BIT(31); + if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || + (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) + rKey.u4KeyIndex |= BIT(30); + } + else { + rKey.u4KeyIndex |= BIT(31); + } + } + else { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + rKey.u4KeyIndex |= BIT(31); //???? + } + if(params->key) + { + //rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + } + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((UINT_32)&(((P_P2P_PARAM_KEY_T)0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddP2PKey, + &rKey, + rKey.u4Length, + FALSE, + FALSE, + TRUE, + TRUE, + &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + + +int mtk_p2p_cfg80211_get_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*) + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int mtk_p2p_cfg80211_del_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_REMOVE_KEY_T prRemoveKey; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&prRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if(mac_addr) + memcpy(prRemoveKey.arBSSID, mac_addr, PARAM_MAC_ADDR_LEN); + prRemoveKey.u4KeyIndex = key_index; + prRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + &prRemoveKey, + prRemoveKey.u4Length, + FALSE, + FALSE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + + +int +mtk_p2p_cfg80211_set_default_key ( + struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index, + bool unicast, + bool multicast + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_station( + struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo + ) +{ + INT_32 i4RetRslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T)NULL; + P2P_STATION_INFO_T rP2pStaInfo; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || + (ndev == NULL) || + (sinfo == NULL) || + (mac == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_get_station\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + sinfo->filled = 0; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, + mac, + &rP2pStaInfo); + + /* Inactive time. */ + sinfo->filled |= STATION_INFO_INACTIVE_TIME; + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int +mtk_p2p_cfg80211_scan ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_scan_request *request + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T)NULL; + P_MSG_P2P_SCAN_REQUEST_T prMsgScanRequest = (P_MSG_P2P_SCAN_REQUEST_T)NULL; + UINT_32 u4MsgSize = 0, u4Idx = 0; + INT_32 i4RetRslt = -EINVAL; + P_RF_CHANNEL_INFO_T prRfChannelInfo = (P_RF_CHANNEL_INFO_T)NULL; + P_P2P_SSID_STRUCT_T prSsidStruct = (P_P2P_SSID_STRUCT_T)NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + + /* [---------Channel---------] [---------SSID---------][---------IE---------] */ + + + do { + if ((wiphy == NULL) || (request == NULL)) { + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (prP2pGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_scan.\n")); + + + if (prP2pGlueInfo->prScanRequest != NULL) { + /* There have been a scan request on-going processing. */ + DBGLOG(P2P, TRACE, ("There have been a scan request on-going processing.\n")); + break; + } + + prP2pGlueInfo->prScanRequest = request; + + /* Should find out why the n_channels so many? */ + if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + request->n_channels = MAXIMUM_OPERATION_CHANNEL_LIST; + DBGLOG(P2P, TRACE, ("Channel list exceed the maximun support.\n")); + } + + u4MsgSize = sizeof(MSG_P2P_SCAN_REQUEST_T) + + (request->n_channels * sizeof(RF_CHANNEL_INFO_T)) + + (request->n_ssids * sizeof(PARAM_SSID_T)) + + request->ie_len; + + prMsgScanRequest = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, u4MsgSize); + + if (prMsgScanRequest == NULL) { + ASSERT(FALSE); + i4RetRslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, ("Generating scan request message.\n")); + + prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + + + + DBGLOG(P2P, TRACE, ("Requesting channel number:%d.\n", request->n_channels)); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); + DBGLOG(P2P, TRACE, ("Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + prChannel->center_freq)); + switch (prChannel->band) { + case IEEE80211_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case IEEE80211_BAND_5GHZ: + prRfChannelInfo->eBand = BAND_5G; + break; + default: + DBGLOG(P2P, TRACE, ("UNKNOWN Band info from supplicant\n")); + prRfChannelInfo->eBand = BAND_NULL; + break; + } + + /* Iteration. */ + prRfChannelInfo++; + } + prMsgScanRequest->u4NumChannel = request->n_channels; + + DBGLOG(P2P, TRACE, ("Finish channel list.\n")); + + /* SSID */ + prSsid = request->ssids; + prSsidStruct = (P_P2P_SSID_STRUCT_T)prRfChannelInfo; + if (request->n_ssids) { + ASSERT(prSsidStruct == &(prMsgScanRequest->arChannelListInfo[u4Idx])); + prMsgScanRequest->prSSID = prSsidStruct; + } + + for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { + COPY_SSID(prSsidStruct->aucSsid, + prSsidStruct->ucSsidLen, + request->ssids->ssid, + request->ssids->ssid_len); + + prSsidStruct++; + prSsid++; + } + + prMsgScanRequest->i4SsidNum = request->n_ssids; + + DBGLOG(P2P, TRACE, ("Finish SSID list:%d.\n", request->n_ssids)); + + /* IE BUFFERS */ + prMsgScanRequest->pucIEBuf = (PUINT_8)prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } + + DBGLOG(P2P, TRACE, ("Finish IE Buffer.\n")); + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgScanRequest, + MSG_SEND_METHOD_BUF); + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} /* mtk_p2p_cfg80211_scan */ + +int mtk_p2p_cfg80211_set_wiphy_params( + struct wiphy *wiphy, + u32 changed + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + + + do { + if (wiphy == NULL) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_set_wiphy_params\n")); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + // TODO: + DBGLOG(P2P, TRACE, ("The RETRY short param is changed.\n")); + } + + if (changed & WIPHY_PARAM_RETRY_LONG) { + // TODO: + DBGLOG(P2P, TRACE, ("The RETRY long param is changed.\n")); + } + + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + // TODO: + DBGLOG(P2P, TRACE, ("The RETRY fragmentation threshold is changed.\n")); + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + // TODO: + DBGLOG(P2P, TRACE, ("The RETRY RTS threshold is changed.\n")); + } + + if (changed & WIPHY_PARAM_COVERAGE_CLASS) { + // TODO: + DBGLOG(P2P, TRACE, ("The coverage class is changed???\n")); + } + + i4Rslt = 0; + } while (FALSE); + + + + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_wiphy_params */ + + + +int +mtk_p2p_cfg80211_join_ibss( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int +mtk_p2p_cfg80211_leave_ibss( + struct wiphy *wiphy, + struct net_device *dev + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int +mtk_p2p_cfg80211_set_txpower( + struct wiphy *wiphy, + enum nl80211_tx_power_setting type, + int mbm + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int +mtk_p2p_cfg80211_get_txpower( + struct wiphy *wiphy, + int *dbm + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + + return -EINVAL; +} + +int +mtk_p2p_cfg80211_set_power_mgmt( + struct wiphy *wiphy, + struct net_device *dev, + bool enabled, + int timeout + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + // TODO: for JB. + + return -EINVAL; +} + +//&&&&&&&&&&&&&&&&&&&&&&&&&& Add for ICS Wi-Fi Direct Support. &&&&&&&&&&&&&&&&&&&&&&& +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +int +mtk_p2p_cfg80211_start_ap ( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)NULL; + PUINT_8 pucBuffer = (PUINT_8)NULL; +// P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; + + do { + if ((wiphy == NULL) || (settings == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_start_ap.\n")); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)cnmMemAlloc( + prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + settings->beacon.head_len + settings->beacon.tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (settings->beacon.head_len != 0) { + kalMemCopy(pucBuffer, settings->beacon.head, settings->beacon.head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = settings->beacon.head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8)((UINT_32)pucBuffer + (UINT_32)settings->beacon.head_len); + } + else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + UINT_8 ucLen = settings->beacon.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + + /*Add TIM IE*/ + // IEEE 802.11 2007 - 7.3.2.6 + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP)/*((u4N2 - u4N1) + 4)*/; // NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) + TIM_IE(pucBuffer)->ucDTIMCount = 0/*prBssInfo->ucDTIMCount*/; // will be overwrite by FW + TIM_IE(pucBuffer)->ucDTIMPeriod = 1; + TIM_IE(pucBuffer)->ucBitmapControl = 0/*ucBitmapControl | (UINT_8)u4N1*/; // will be overwrite by FW + ucLen += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } + else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)cnmMemAlloc( + prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_START_AP_T)); + + if (prP2pStartAPMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pStartAPMsg->rMsgHdr.eMsgId = MID_MNY_P2P_START_AP; + + prP2pStartAPMsg->fgIsPrivacy = settings->privacy; + + prP2pStartAPMsg->u4BcnInterval = settings->beacon_interval; + + prP2pStartAPMsg->u4DtimPeriod = settings->dtim_period; + + /* Copy NO SSID. */ + prP2pStartAPMsg->ucHiddenSsidType = settings->hidden_ssid; + + COPY_SSID(prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen, + settings->ssid, + settings->ssid_len); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pStartAPMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + + +///////////////////////// + /** + * struct cfg80211_ap_settings - AP configuration + * + * Used to configure an AP interface. + * + * @beacon: beacon data + * @beacon_interval: beacon interval + * @dtim_period: DTIM period + * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from + * user space) + * @ssid_len: length of @ssid + * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames + * @crypto: crypto settings + * @privacy: the BSS uses privacy + * @auth_type: Authentication type (algorithm) + * @inactivity_timeout: time in seconds to determine station's inactivity. + */ +// struct cfg80211_ap_settings { +// struct cfg80211_beacon_data beacon; +// +// int beacon_interval, dtim_period; +// const u8 *ssid; +// size_t ssid_len; +// enum nl80211_hidden_ssid hidden_ssid; +// struct cfg80211_crypto_settings crypto; +// bool privacy; +// enum nl80211_auth_type auth_type; +// int inactivity_timeout; +// }; +//////////////////// + + return i4Rslt; +} /* mtk_p2p_cfg80211_start_ap */ + + +int +mtk_p2p_cfg80211_change_beacon ( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)NULL; + PUINT_8 pucBuffer = (PUINT_8)NULL; + + do { + if ((wiphy == NULL) || (info == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_change_beacon.\n")); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)cnmMemAlloc( + prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + info->head_len + info->tail_len)); + + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (info->head_len != 0) { + kalMemCopy(pucBuffer, info->head, info->head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = info->head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8)((UINT_32)pucBuffer + (UINT_32)info->head_len); + } + else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + UINT_8 ucLen = info->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + + /*Add TIM IE*/ + // IEEE 802.11 2007 - 7.3.2.6 + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP)/*((u4N2 - u4N1) + 4)*/; // NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) + TIM_IE(pucBuffer)->ucDTIMCount = 0/*prBssInfo->ucDTIMCount*/; // will be overwrite by FW + TIM_IE(pucBuffer)->ucDTIMPeriod = 1; + TIM_IE(pucBuffer)->ucBitmapControl = 0/*ucBitmapControl | (UINT_8)u4N1*/; // will be overwrite by FW + ucLen += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + kalMemCopy(pucBuffer, info->tail, info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } + else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + +//////////////////////////// +/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @head_len: length of @head + * @tail_len: length of @tail + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) + */ +//struct cfg80211_beacon_data { +// const u8 *head, *tail; +// const u8 *beacon_ies; +// const u8 *proberesp_ies; +// const u8 *assocresp_ies; +// const u8 *probe_resp; + +// size_t head_len, tail_len; +// size_t beacon_ies_len; +// size_t proberesp_ies_len; +// size_t assocresp_ies_len; +// size_t probe_resp_len; +//}; + +//////////////////////////// + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +#else +int +mtk_p2p_cfg80211_add_set_beacon ( + struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *info + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)NULL; + PUINT_8 pucBuffer = (PUINT_8)NULL; + P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; + + do { + if ((wiphy == NULL) || (info == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_add_set_beacon.\n")); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T)cnmMemAlloc( + prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + info->head_len + info->tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (info->head_len != 0) { + kalMemCopy(pucBuffer, info->head, info->head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = info->head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8)((UINT_32)pucBuffer + (UINT_32)info->head_len); + } + else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + UINT_8 ucLen = info->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + + /*Add TIM IE*/ + // IEEE 802.11 2007 - 7.3.2.6 + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP)/*((u4N2 - u4N1) + 4)*/; // NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) + TIM_IE(pucBuffer)->ucDTIMCount = 0/*prBssInfo->ucDTIMCount*/; // will be overwrite by FW + TIM_IE(pucBuffer)->ucDTIMPeriod = 1; + TIM_IE(pucBuffer)->ucBitmapControl = 0/*ucBitmapControl | (UINT_8)u4N1*/; // will be overwrite by FW + ucLen += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + kalMemCopy(pucBuffer, info->tail, info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } + else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T)cnmMemAlloc( + prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_START_AP_T)); + + if (prP2pStartAPMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pStartAPMsg->rMsgHdr.eMsgId = MID_MNY_P2P_START_AP; + + prP2pStartAPMsg->fgIsPrivacy = FALSE; + + prP2pStartAPMsg->u4BcnInterval = info->interval; + + prP2pStartAPMsg->u4DtimPeriod = info->dtim_period; + + /* Copy NO SSID. */ + prP2pStartAPMsg->ucHiddenSsidType = ENUM_HIDDEN_SSID_NONE; + +#if 0 + if (info->head_len > OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)) { + P_WLAN_BEACON_FRAME_T prWlanBcnFrame = info->head; + + prSsidIE = (P_IE_HDR_T)p2pFuncGetSpecIE(prGlueInfo->prAdapter, + (PUINT_8)prWlanBcnFrame->aucInfoElem, + (info->head_len - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)), + ELEM_ID_SSID, + NULL); + + kalMemCopy(prP2pStartAPMsg->aucSsid, SSID_IE(prSsidIE)->aucSSID, IE_LEN(prSsidIE)); + + } +#endif + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pStartAPMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} +/* mtk_p2p_cfg80211_add_set_beacon */ +#endif + +int +mtk_p2p_cfg80211_stop_ap ( + struct wiphy *wiphy, + struct net_device *dev + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_SWITCH_OP_MODE_T prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T)NULL; + + do { + if (wiphy == NULL) { + break; + } + + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_stop_ap.\n")); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // Switch OP MOde. + prP2pSwitchMode = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_SWITCH_OP_MODE_T)); + + if (prP2pSwitchMode == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pSwitchMode->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pSwitchMode, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + + return i4Rslt; +} /* mtk_p2p_cfg80211_stop_ap */ + +// TODO: +int +mtk_p2p_cfg80211_deauth ( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) + , void *cookie +#endif + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // not implemented yet + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_deauth.\n")); + + return -EINVAL; +} /* mtk_p2p_cfg80211_deauth */ + + +// TODO: +int +mtk_p2p_cfg80211_disassoc ( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) + , void *cookie +#endif + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_disassoc.\n")); + + // not implemented yet + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + + +int +mtk_p2p_cfg80211_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 + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + P_MSG_P2P_CHNL_REQUEST_T prMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T)NULL; + + + do { + if ((wiphy == NULL) || + (dev == NULL) || + (chan == NULL) || + (cookie == NULL)) { + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + *cookie = prGlueP2pInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_remain_on_channel\n")); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4Duration = duration; + + + mtk_p2p_cfg80211func_channel_format_switch(chan, + channel_type, + &prMsgChnlReq->rChannelInfo, + &prMsgChnlReq->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgChnlReq, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + i4Rslt = 0; + } while (FALSE); + + + return i4Rslt; +} +/* mtk_p2p_cfg80211_remain_on_channel */ + + +int +mtk_p2p_cfg80211_cancel_remain_on_channel ( + struct wiphy *wiphy, + struct net_device *dev, + u64 cookie + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T)NULL; + + do { + if ((wiphy == NULL) || (dev == NULL)) { + break; + } + + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_ABORT_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_cancel_remain_on_channel\n")); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgChnlAbort, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ + +int +mtk_p2p_cfg80211_mgmt_tx ( + struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, + size_t len, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + bool no_cck, + bool dont_wait_for_ack, +#endif + u64 *cookie + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_P2P_MGMT_TX_REQUEST_T)NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T)NULL; + PUINT_8 pucFrameBuf = (PUINT_8)NULL; + + do { + if ((wiphy == NULL) || + (buf == NULL) || + (len == 0) || + (dev == NULL) || + (cookie == NULL)) { + break; + } + + //DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_mgmt_tx\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + *cookie = prGlueP2pInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32)(len + MAC_TX_RESERVED_FIELD)); + + if ((prMsgTxReq->prMgmtMsduInfo = prMgmtFrame) == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + + pucFrameBuf = (PUINT_8)((UINT_32)prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + prMgmtFrame->u2FrameLength = len; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgTxReq, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) { + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + } + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx */ + + + +int +mtk_p2p_cfg80211_change_bss ( + struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + + switch (params->use_cts_prot) { + case -1: + DBGLOG(P2P, TRACE, ("CTS protection no change\n")); + break; + case 0: + DBGLOG(P2P, TRACE, ("CTS protection disable.\n")); + break; + case 1: + DBGLOG(P2P, TRACE, ("CTS protection enable\n")); + break; + default: + DBGLOG(P2P, TRACE, ("CTS protection unknown\n")); + break; + } + + + + switch (params->use_short_preamble) { + case -1: + DBGLOG(P2P, TRACE, ("Short prreamble no change\n")); + break; + case 0: + DBGLOG(P2P, TRACE, ("Short prreamble disable.\n")); + break; + case 1: + DBGLOG(P2P, TRACE, ("Short prreamble enable\n")); + break; + default: + DBGLOG(P2P, TRACE, ("Short prreamble unknown\n")); + break; + } + + + +#if 0 + // not implemented yet + p2pFuncChangeBssParam(prGlueInfo->prAdapter, + prBssInfo->fgIsProtection, + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortSlotTime, + // Basic rates + // basic rates len + // ap isolate + // ht opmode. + ); +#else + i4Rslt = 0; +#endif + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_bss */ + + + +int +mtk_p2p_cfg80211_del_station ( + struct wiphy *wiphy, + struct net_device *dev, + u8 *mac + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T)NULL; + UINT_8 aucBcMac[] = BC_MAC_ADDR; + + + do { + if ((wiphy == NULL) || + (dev == NULL)) { + break; + } + + if (mac == NULL) { + mac = aucBcMac; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_del_station.\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + //prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); + prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T)cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ + + +int +mtk_p2p_cfg80211_connect ( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_connect_params *sme + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T)NULL; + + + do { + if ((wiphy == NULL) || + (dev == NULL) || + (sme == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_connect.\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T)cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, (sizeof(MSG_P2P_CONNECTION_REQUEST_T) + sme->ie_len)); + + if (prConnReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, + prConnReqMsg->rSsid.ucSsidLen, + sme->ssid, + sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, sme->bssid); + + DBGLOG(P2P, TRACE, ("Assoc Req IE Buffer Length:%d\n", sme->ie_len)); + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + mtk_p2p_cfg80211func_channel_format_switch(sme->channel, + NL80211_CHAN_NO_HT, + &prConnReqMsg->rChannelInfo, + &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prConnReqMsg, + MSG_SEND_METHOD_BUF); + + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_connect */ + +int +mtk_p2p_cfg80211_disconnect ( + struct wiphy *wiphy, + struct net_device *dev, + u16 reason_code + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)NULL; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + do { + if ((wiphy == NULL) || + (dev == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_disconnect.\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +// prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); + prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (prDisconnMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prDisconnMsg, + MSG_SEND_METHOD_UNBUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + + +int +mtk_p2p_cfg80211_change_iface ( + IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, + IN u32 *flags, + IN struct vif_params *params + ) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchModeMsg = (P_MSG_P2P_SWITCH_OP_MODE_T)NULL; + + do { + if ((wiphy == NULL) || + (ndev == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_change_iface.\n")); + + if (ndev->ieee80211_ptr) { + ndev->ieee80211_ptr->iftype = type; + } + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + + // Switch OP MOde. + prSwitchModeMsg = (P_MSG_P2P_SWITCH_OP_MODE_T)cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_SWITCH_OP_MODE_T)); + + if (prSwitchModeMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, ("NL80211_IFTYPE_P2P_CLIENT.\n")); + case NL80211_IFTYPE_STATION: + if (type == NL80211_IFTYPE_STATION) { + DBGLOG(P2P, TRACE, ("NL80211_IFTYPE_STATION.\n")); + } + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, ("NL80211_IFTYPE_AP.\n")); + case NL80211_IFTYPE_P2P_GO: + if (type == NL80211_IFTYPE_P2P_GO) { + DBGLOG(P2P, TRACE, ("NL80211_IFTYPE_P2P_GO not AP.\n")); + } + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + break; + default: + DBGLOG(P2P, TRACE, ("Other type :%d .\n", type)); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + break; + } + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_change_iface */ + + +int +mtk_p2p_cfg80211_set_channel ( + IN struct wiphy *wiphy, + IN struct net_device *dev, + IN struct ieee80211_channel *chan, + IN enum nl80211_channel_type channel_type) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + RF_CHANNEL_INFO_T rRfChnlInfo; + + do { + if ((wiphy == NULL) || + (dev == NULL) || + (chan == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_set_channel.\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + mtk_p2p_cfg80211func_channel_format_switch(chan, + channel_type, + &rRfChnlInfo, + NULL); + + p2pFuncSetChannel(prGlueInfo->prAdapter, &rRfChnlInfo); + + i4Rslt = 0; + } +while (FALSE); + + return i4Rslt; + +} +/* mtk_p2p_cfg80211_set_channel */ + +int +mtk_p2p_cfg80211_set_bitrate_mask ( + IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask + ) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + + do { + if ((wiphy == NULL) || + (dev == NULL) || + (mask == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_set_bitrate_mask\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + // TODO: Set bitrate mask of the peer? + + i4Rslt = 0; + } +while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + + +void +mtk_p2p_cfg80211_mgmt_frame_register ( + IN struct wiphy *wiphy, + IN struct net_device *dev, + IN u16 frame_type, + IN bool reg + ) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T)NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL; + + do { + if ((wiphy == NULL) || + (dev == NULL)) { + break; + } + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_mgmt_frame_register\n")); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, ("Open packet filer probe request\n")); + } + else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, ("Close packet filer probe request\n")); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, ("Open packet filer action frame.\n")); + } + else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, ("Close packet filer action frame.\n")); + } + break; + default: + DBGLOG(P2P, ERROR, ("Ask frog to add code for mgmt:%x\n", frame_type)); + break; + } + + + + if((prGlueInfo->prAdapter != NULL) && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)){ + + prGlueInfo->u4Flag |= GLUE_FLAG_FRAME_FILTER; + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) { + DBGLOG(P2P, TRACE, ("It is in interrupt level\n")); + } + } + + +#if 0 + + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T)cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMgmtFrameRegister, + MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + + + return; +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + + +BOOLEAN +mtk_p2p_cfg80211func_channel_format_switch ( + IN struct ieee80211_channel *channel, + IN enum nl80211_channel_type channel_type, + IN P_RF_CHANNEL_INFO_T prRfChnlInfo, + IN P_ENUM_CHNL_EXT_T prChnlSco + ) +{ + BOOLEAN fgIsValid = FALSE; + + do { + if (channel == NULL) { + break; + } + + if (prRfChnlInfo) { + prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000); + + switch (channel->band) { + case IEEE80211_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case IEEE80211_BAND_5GHZ: + prRfChnlInfo->eBand = BAND_5G; + break; + default: + prRfChnlInfo->eBand = BAND_2G4; + break; + } + + } + + + if (prChnlSco) { + + switch (channel_type) { + case NL80211_CHAN_NO_HT: + *prChnlSco = CHNL_EXT_SCN; + break; + case NL80211_CHAN_HT20: + *prChnlSco = CHNL_EXT_SCN; + break; + case NL80211_CHAN_HT40MINUS: + *prChnlSco = CHNL_EXT_SCA; + break; + case NL80211_CHAN_HT40PLUS: + *prChnlSco = CHNL_EXT_SCB; + break; + default: + ASSERT(FALSE); + *prChnlSco = CHNL_EXT_SCN; + break; + } + } + + fgIsValid = TRUE; + } +while (FALSE); + + return fgIsValid; +} +/* mtk_p2p_cfg80211func_channel_format_switch */ + + +#if CONFIG_NL80211_TESTMODE +int mtk_p2p_cfg80211_testmode_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS)NULL; + BOOLEAN fgIsValid = FALSE; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_testmode_cmd\n")); + + if(data && len) + prParams = (P_NL80211_DRIVER_TEST_PARAMS)data; + + if(prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~ BITS(24,31); + } + else { + /* Old version*/ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + fgIsValid = TRUE; + return fgIsValid; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~ BITS(24,31); + + if(prParams){ + switch(prParams->index){ + case 1: /* P2P Simga */ + if(mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len)) + fgIsValid = TRUE; + break; +#if CFG_SUPPORT_WFD + case 2: /* WFD */ + if(mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len)) + fgIsValid= TRUE; + break; +#endif + case 3: /* Hotspot Client Management */ + if(mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(wiphy, data, len)) + fgIsValid = TRUE; + break; + default: + fgIsValid = TRUE; + break; + } + } + + return fgIsValid; + +} + + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + NL80211_DRIVER_TEST_PRE_PARAMS rParams; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + UINT_32 index_mode; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&rParams, sizeof(NL80211_DRIVER_TEST_PRE_PARAMS)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd\n")); + + if(data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, ("NL80211_ATTR_TESTDATA,idx_mode=%d idx=%d value=%lu\n", + (INT_16)rParams.idx_mode, (INT_16)rParams.idx, rParams.value)); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 100: /* Oper CH */ + // 20110920 - frog: User configurations are placed in ConnSettings. + // prP2pConnSettings->ucOperatingChnl = value; + break; + case 101: /* Local config Method, for P2P SDK */ + prP2pConnSettings->u2LocalConfigMethod = value; + break; + case 102: /* Sigma P2p reset */ + //kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); + //prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; + p2pFsmUninit(prGlueInfo->prAdapter); + p2pFsmInit(prGlueInfo->prAdapter); + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + //status = mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + + break; + default: + break; + } + + return status; + +} + + +int +mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_P2P_SIGMA_PARAMS prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_testmode_p2p_sigma_cmd\n")); + + if(data && len) + prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS)data; + + index = (INT_32)prParams->idx; + value = (INT_32)prParams->value; + + DBGLOG(P2P, TRACE, ("NL80211_ATTR_TESTDATA, idx=%lu value=%lu\n", + (INT_32)prParams->idx, (INT_32)prParams->value)); + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + // only to apply setting when setting NOA count + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + //status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 100: /* Oper CH */ + // 20110920 - frog: User configurations are placed in ConnSettings. + // prP2pConnSettings->ucOperatingChnl = value; + break; + case 101: /* Local config Method, for P2P SDK */ + prP2pConnSettings->u2LocalConfigMethod = value; + break; + case 102: /* Sigma P2p reset */ + //kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); + //prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + //status = mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, + sizeof(value), + FALSE, + FALSE, + TRUE, + TRUE, + &u4Leng); + + break; + case 109: /* Max Clients*/ + kalP2PSetMaxClients(prGlueInfo, value); + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD +int +mtk_p2p_cfg80211_testmode_wfd_update_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_WFD_PARAMS prParams = (P_NL80211_DRIVER_WFD_PARAMS)NULL; + int status = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prParams = (P_NL80211_DRIVER_WFD_PARAMS)data; + + + DBGLOG(P2P, INFO, ("mtk_p2p_cfg80211_testmode_wfd_update_cmd\n")); + +#if 1 + + DBGLOG(P2P, INFO,("WFD Enable:%x\n", prParams->WfdEnable)); + DBGLOG(P2P, INFO,("WFD Session Available:%x\n", prParams->WfdSessionAvailable)); + DBGLOG(P2P, INFO,("WFD Couple Sink Status:%x\n", prParams->WfdCoupleSinkStatus)); + //aucReserved0[2] + DBGLOG(P2P, INFO,("WFD Device Info:%x\n", prParams->WfdDevInfo)); + DBGLOG(P2P, INFO,("WFD Control Port:%x\n", prParams->WfdControlPort)); + DBGLOG(P2P, INFO,("WFD Maximum Throughput:%x\n", prParams->WfdMaximumTp)); + DBGLOG(P2P, INFO,("WFD Extend Capability:%x\n", prParams->WfdExtendCap)); + DBGLOG(P2P, INFO,("WFD Couple Sink Addr "MACSTR" \n", MAC2STR(prParams->WfdCoupleSinkAddress))); + DBGLOG(P2P, INFO,("WFD Associated BSSID "MACSTR" \n", MAC2STR(prParams->WfdAssociatedBssid))); + //UINT_8 aucVideolp[4]; + //UINT_8 aucAudiolp[4]; + DBGLOG(P2P, INFO,("WFD Video Port:%x\n", prParams->WfdVideoPort)); + DBGLOG(P2P, INFO,("WFD Audio Port:%x\n", prParams->WfdAudioPort)); + DBGLOG(P2P, INFO,("WFD Flag:%x\n", prParams->WfdFlag)); + DBGLOG(P2P, INFO,("WFD Policy:%x\n", prParams->WfdPolicy)); + DBGLOG(P2P, INFO,("WFD State:%x\n", prParams->WfdState)); + //UINT_8 aucWfdSessionInformationIE[24*8]; + DBGLOG(P2P, INFO,("WFD Session Info Length:%x\n", prParams->WfdSessionInformationIELen)); + //UINT_8 aucReserved1[2]; + DBGLOG(P2P, INFO,("WFD Primary Sink Addr "MACSTR" \n", MAC2STR(prParams->aucWfdPrimarySinkMac))); + DBGLOG(P2P, INFO,("WFD Secondary Sink Addr "MACSTR" \n", MAC2STR(prParams->aucWfdSecondarySinkMac))); + DBGLOG(P2P, INFO,("WFD Advanced Flag:%x\n", prParams->WfdAdvanceFlag)); + DBGLOG(P2P, INFO,("WFD Sigma mode:%x\n", prParams->WfdSigmaMode)); + //UINT_8 aucReserved2[64]; + //UINT_8 aucReserved3[64]; + //UINT_8 aucReserved4[64]; + +#endif + + prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, &prParams->WfdCmdType, sizeof(WFD_CFG_SETTINGS_T)); + + prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate == NULL) { + ASSERT(FALSE); + return status; + } + + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prMsgWfdCfgUpdate, + MSG_SEND_METHOD_BUF); +#if 0 // Test Only +// prWfdCfgSettings->ucWfdEnable = 1; +// prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; + prWfdCfgSettings->u2WfdDevInfo = 123; + prWfdCfgSettings->u2WfdControlPort = 456; + prWfdCfgSettings->u2WfdMaximumTp = 789; + + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_SINK_INFO_VALID; + prWfdCfgSettings->ucWfdCoupleSinkStatus = 0xAB; + { + UINT_8 aucTestAddr[MAC_ADDR_LEN] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22}; + COPY_MAC_ADDR(prWfdCfgSettings->aucWfdCoupleSinkAddress, aucTestAddr); + } + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_EXT_CAPABILITY_VALID; + prWfdCfgSettings->u2WfdExtendCap = 0xCDE; + +#endif + + return status; + +} +#endif /* CFG_SUPPORT_WFD */ + + + +int +mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_hotspot_block_PARAMS prParams = (P_NL80211_DRIVER_hotspot_block_PARAMS)NULL; + int fgIsValid = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if(data && len) + prParams = (P_NL80211_DRIVER_hotspot_block_PARAMS)data; + + DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd\n")); + + fgIsValid = kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked); + + return fgIsValid; + +} + +#endif + + +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) + +#endif // CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c new file mode 100755 index 000000000000..8fd89a40f35a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c @@ -0,0 +1,518 @@ +/* +** $Id: @(#) gl_p2p_init.c@@ +*/ + +/*! \file gl_p2p_init.c + \brief init and exit routines of Linux driver interface for Wi-Fi Direct + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define P2P_MODE_INF_NAME "p2p%d"; +#define AP_MODE_INF_NAME "ap%d"; +//#define MAX_INF_NAME_LEN 15 +//#define MIN_INF_NAME_LEN 1 + +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* Get interface name and running mode from module insertion parameter +* Usage: insmod p2p.ko mode=1 +* default: interface name is p2p%d +* running mode is P2P +*/ +static PUCHAR ifname = P2P_MODE_INF_NAME; +static UINT_16 mode = RUNNING_P2P_MODE; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if defined(CONFIG_HAS_EARLYSUSPEND) +extern int glRegisterEarlySuspend( + struct early_suspend *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend *prDesc); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief check interface name parameter is valid or not +* if invalid, set ifname to P2P_MODE_INF_NAME +* +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pCheckInterfaceName( + VOID + ) +{ + + if(mode) { + mode = RUNNING_AP_MODE; + ifname = AP_MODE_INF_NAME; + } +#if 0 + UINT_32 ifLen = 0; + + if(ifname) { + ifLen = strlen(ifname); + + if(ifLen > MAX_INF_NAME_LEN) { + ifname[MAX_INF_NAME_LEN] = '\0'; + } + else if( ifLen < MIN_INF_NAME_LEN ) { + ifname = P2P_MODE_INF_NAME; + } + } else { + ifname = P2P_MODE_INF_NAME; + } +#endif +} + + +extern UINT_8 g_aucBufIpAddr[32]; + +static void wlanP2PEarlySuspend(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + + printk(KERN_INFO "*********p2pEarlySuspend************\n"); + + if(!wlanExportGlueInfo(&prGlueInfo)) { + printk(KERN_INFO "*********p2pEarlySuspend ignored************\n"); + return; + } + + ASSERT(prGlueInfo); + // <1> Sanity check and acquire the net_device + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + // <3> get the IPv4 address + if(!prDev || !(prDev->ip_ptr)||\ + !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ + printk(KERN_INFO "ip is not avaliable.\n"); + return; + } + + // <4> copy the IPv4 address + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + printk(KERN_INFO"ip is %d.%d.%d.%d\n", + ip[0],ip[1],ip[2],ip[3]); + + // todo: traverse between list to find whole sets of IPv4 addresses + if (!((ip[0] == 0) && + (ip[1] == 0) && + (ip[2] == 0) && + (ip[3] == 0))) { + u4NumIPv4++; + } + +#ifdef CONFIG_IPV6 + // <5> get the IPv6 address + if(!prDev || !(prDev->ip6_ptr)||\ + !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ + printk(KERN_INFO "ipv6 is not avaliable.\n"); + return; + } + // <6> copy the IPv6 address + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0],ip6[1],ip6[2],ip6[3], + ip6[4],ip6[5],ip6[6],ip6[7], + ip6[8],ip6[9],ip6[10],ip6[11], + ip6[12],ip6[13],ip6[14],ip6[15] + ); + // todo: traverse between list to find whole sets of IPv6 addresses + + if (!((ip6[0] == 0) && + (ip6[1] == 0) && + (ip6[2] == 0) && + (ip6[3] == 0) && + (ip6[4] == 0) && + (ip6[5] == 0))) { + } + +#endif + // <7> set up the ARP filter + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +// UINT_8 aucBuf[32] = {0}; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + +// prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); // TODO: frog. The pointer is not right. + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + + (UINT_32) (prParamNetAddr->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); +#endif + } +#ifdef CONFIG_IPV6 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); +// prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + + (UINT_32) (prParamNetAddr->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID)prParamNetAddrList, + u4Len, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%lx\n", rStatus); + } + } +} + + +static void wlanP2PLateResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack +#endif + + printk(KERN_INFO "*********wlanP2PLateResume************\n"); + if(!wlanExportGlueInfo(&prGlueInfo)) { + printk(KERN_INFO "*********p2pLateResume ignored************\n"); + return; + } + + ASSERT(prGlueInfo); + // <1> Sanity check and acquire the net_device + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + // <3> get the IPv4 address + if(!prDev || !(prDev->ip_ptr)||\ + !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ + printk(KERN_INFO "ip is not avaliable.\n"); + return; + } + + // <4> copy the IPv4 address + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + printk(KERN_INFO"ip is %d.%d.%d.%d\n", + ip[0],ip[1],ip[2],ip[3]); + +#ifdef CONFIG_IPV6 + // <5> get the IPv6 address + if(!prDev || !(prDev->ip6_ptr)||\ + !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ + printk(KERN_INFO "ipv6 is not avaliable.\n"); + return; + } + // <6> copy the IPv6 address + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0],ip6[1],ip6[2],ip6[3], + ip6[4],ip6[5],ip6[6],ip6[7], + ip6[8],ip6[9],ip6[10],ip6[11], + ip6[12],ip6[13],ip6[14],ip6[15] + ); +#endif + // <7> clear the ARP filter + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +// UINT_8 aucBuf[32] = {0}; + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID)prParamNetAddrList, + u4Len, + FALSE, + FALSE, + TRUE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%lx\n", rStatus); + } + } +} + +#if defined(CONFIG_HAS_EARLYSUSPEND) +static struct early_suspend mt6620_p2p_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void p2p_early_suspend(struct early_suspend *h) +{ + printk(KERN_INFO "*********wlanP2P_early_suspend************\n"); + wlanP2PEarlySuspend(); +} + +static void p2p_late_resume(struct early_suspend *h) +{ + printk(KERN_INFO "*********wlanP2P_late_resume************\n"); + wlanP2PLateResume(); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p init procedure, include register pointer to wlan +* glue register p2p +* set p2p registered flag +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pLaunch( + P_GLUE_INFO_T prGlueInfo + ) +{ + + printk("p2p Launch\n"); + + if(prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + printk("p2p already registered\n"); + return FALSE; + } + else if(glRegisterP2P(prGlueInfo, ifname, (BOOLEAN)mode)) { + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + + printk("Launch success, fgIsP2PRegistered TRUE.\n"); + +#if defined(CONFIG_HAS_EARLYSUSPEND) + /* Here, we register the early suspend and resume callback */ + glRegisterEarlySuspend(&mt6620_p2p_early_suspend_desc, p2p_early_suspend, p2p_late_resume); +#endif + + return TRUE; + } + else { + printk("Launch Fail\n"); + } + + return FALSE; +} + + +VOID +p2pSetMode ( + IN BOOLEAN fgIsAPMOde + ) +{ + if (fgIsAPMOde) { + mode = RUNNING_AP_MODE; + ifname = AP_MODE_INF_NAME; + } + else { + mode = RUNNING_P2P_MODE; + ifname = P2P_MODE_INF_NAME; + } + + return; +} /* p2pSetMode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p exit procedure, include unregister pointer to wlan +* glue unregister p2p +* set p2p registered flag + +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pRemove( + P_GLUE_INFO_T prGlueInfo + ) +{ + if(prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + printk("p2p is not Registered.\n"); + return FALSE; + } + else { + +#if defined(CONFIG_HAS_EARLYSUSPEND) + glUnregisterEarlySuspend(&mt6620_p2p_early_suspend_desc); +#endif + /*Check p2p fsm is stop or not. If not then stop now*/ + if(IS_P2P_ACTIVE(prGlueInfo->prAdapter)) { + p2pStopImmediate(prGlueInfo); + } + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + glUnregisterP2P(prGlueInfo); + /*p2p is removed successfully*/ + return TRUE; + } + return FALSE; +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +static int initP2P(void) +{ + P_GLUE_INFO_T prGlueInfo; + + /*check interface name validation*/ + p2pCheckInterfaceName(); + + printk( KERN_INFO DRV_NAME "InitP2P, Ifname: %s, Mode: %s\n", ifname, mode ? "AP":"P2P"); + + /*register p2p init & exit function to wlan sub module handler*/ + wlanSubModRegisterInitExit(p2pLaunch, p2pRemove, P2P_MODULE); + + /*if wlan is not start yet, do nothing + * p2pLaunch will be called by txthread while wlan start + */ + /*if wlan is not started yet, return FALSE*/ + if(wlanExportGlueInfo(&prGlueInfo)) { + wlanSubModInit(prGlueInfo); + return ( prGlueInfo->prAdapter->fgIsP2PRegistered? 0: -EIO); + } + + return 0; +} /* end of initP2P() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +//1 Module Leave Point +static VOID __exit exitP2P(void) +{ + P_GLUE_INFO_T prGlueInfo; + + printk( KERN_INFO DRV_NAME "ExitP2P\n"); + + /*if wlan is not started yet, return FALSE*/ + if(wlanExportGlueInfo(&prGlueInfo)) { + wlanSubModExit(prGlueInfo); + } + /*UNregister p2p init & exit function to wlan sub module handler*/ + wlanSubModRegisterInitExit(NULL, NULL, P2P_MODULE); +} /* end of exitP2P() */ +#endif + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c new file mode 100755 index 000000000000..bb48193958dd --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c @@ -0,0 +1,1629 @@ +/* +** $Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_kal.c + \brief + +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "net/cfg80211.h" +#include "precomp.h" + +extern BOOLEAN +wextSrchDesiredWPAIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +BOOLEAN +kalP2pFuncGetChannelType( + IN ENUM_CHNL_EXT_T rChnlSco, + OUT enum nl80211_channel_type *channel_type + ); + + +struct ieee80211_channel * +kalP2pFuncGetChannelEntry( + IN P_GL_P2P_INFO_T prP2pInfo, + IN P_RF_CHANNEL_INFO_T prChannelInfo + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T +kalP2PGetState ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->eState; +} /* end of kalP2PGetState() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to update the assoc req to p2p +* +* \param[in] +* prGlueInfo +* pucFrameBody +* u4FrameBodyLen +* fgReassocRequest +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PUpdateAssocInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, + IN BOOLEAN fgReassocRequest + ) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +// unsigned char aucExtraInfoBuf[200]; + PUINT_8 cp; + + memset(&wrqu, 0, sizeof(wrqu)); + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + else { + if (u4FrameBodyLen < 9) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2*/ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } + else { + /* Capability information field 2 */ + /* Listen interval field 2*/ + cp += 4; + u4FrameBodyLen -= 4; + } + + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPSIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + //printk("wextSrchDesiredWPSIE!!\n"); + /* WPS IE found */ + } + else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0x30, &pucDesiredIE)) { + //printk("wextSrchDesiredWPAIE!!\n"); + /* RSN IE found */ + } + else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + //printk("wextSrchDesiredWPAIE!!\n"); + /* WPA IE found */ + } + else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVASSOCREQIE, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetState ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eState, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucRole + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if(eState == PARAM_MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_CONNECTED; + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_STA_CONNECT="MACSTR, MAC2STR(rPeerAddr)); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + } + else if(eState == PARAM_MEDIA_STATE_DISCONNECTED) { + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_STA_DISCONNECT="MACSTR, MAC2STR(rPeerAddr)); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + } + else { + ASSERT(0); + } + + return; +} /* end of kalP2PSetState() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalP2PGetFreqInKHz( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +kalP2PGetRole( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->ucRole; +} /* end of kalP2PGetRole() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct role +* +* \param[in] +* prGlueInfo +* ucResult +* 0: successful +* 1: error +* ucRole +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetRole( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, + IN PUINT_8 pucSSID, + IN UINT_8 ucSSIDLen, + IN UINT_8 ucRole + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + memset(&evt, 0, sizeof(evt)); + + if(ucResult == 0) { + prGlueInfo->prP2PInfo->ucRole = ucRole; + } + + if (pucSSID) + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, 1/* persistence or not */, pucSSID[7], pucSSID[8]); + else + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, 1/* persistence or not */, '0', '0'); + + evt.data.length = strlen(aucBuffer); + + //if (pucSSID) + // printk("P2P GO SSID DIRECT-%c%c\n", pucSSID[7], pucSSID[8]); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* end of kalP2PSetRole() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the cipher for p2p +* +* \param[in] +* prGlueInfo +* u4Cipher +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetCipher( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Cipher + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + prGlueInfo->prP2PInfo->u4CipherPairwise = u4Cipher; + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the cipher, return for cipher is ccmp +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE: cipher is ccmp +* FALSE: cipher is none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalP2PGetCipher ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +BOOLEAN +kalP2PGetCcmpCipher ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + + +BOOLEAN +kalP2PGetTkipCipher ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetWscMode ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucWscMode + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + prGlueInfo->prP2PInfo->ucWSCRunning = ucWscMode; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +kalP2PGetWscMode ( + IN P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + return (prGlueInfo->prP2PInfo->ucWSCRunning); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the wsc ie length +* +* \param[in] +* prGlueInfo +* ucType : 0 for beacon, 1 for probe req, 2 for probe resp +* +* \return +* The WSC IE length +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 +kalP2PCalWSC_IELen ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType + ) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 3); + + return prGlueInfo->prP2PInfo->u2WSCIELen[ucType]; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to copy the wsc ie setting from p2p supplicant +* +* \param[in] +* prGlueInfo +* +* \return +* The WPS IE length +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PGenWSC_IE ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType, + IN PUINT_8 pucBuffer + ) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T)NULL; + + do { + if ((prGlueInfo == NULL) || + (ucType >= 3) || + (pucBuffer == NULL)) { + break; + } + + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(pucBuffer, prGlP2pInfo->aucWSCIE[ucType], prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + + return; +} + + +VOID +kalP2PUpdateWSC_IE ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType, + IN PUINT_8 pucBuffer, + IN UINT_16 u2BufferLength + ) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T)NULL; + + do { + if ((prGlueInfo == NULL) || + (ucType >= 3) || + ((u2BufferLength > 0) && (pucBuffer == NULL))) { + break; + } + + + if (u2BufferLength > 400) { + DBGLOG(P2P, ERROR, ("Buffer length is not enough, GLUE only 400 bytes but %d received\n", u2BufferLength)); + ASSERT(FALSE); + break; + } + + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + + } while (FALSE); + + return; +} /* kalP2PUpdateWSC_IE */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device connection request +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PIndicateConnReq( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucDevName, + IN INT_32 u4NameLength, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, + IN INT_32 i4ActiveConfigMethod + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_REQ_DEVICE_INFO access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, + pucDevName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod = i4ActiveConfigMethod; + + // prepare event structure + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_DVC_REQ"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* end of kalP2PIndicateConnReq() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for device connection request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationIndication ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, + IN UINT_8 ucInvitationType, + IN PUINT_8 pucGroupBssid + ) +{ +#if 1 + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = (UINT_32)((prP2pDevDesc->u2NameLength > 32)? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, + prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqGroupAddr, pucGroupBssid); + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = (INT_32)(prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo->ucInvitationType = ucInvitationType; + + // prepare event structure + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_INV_INDICATE"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + return; + +#else + P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; + + do { + ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); + + + // Not a real solution + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (prP2pConnReq == NULL) { + break; + } + + + kalMemZero(prP2pConnReq, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; + + COPY_MAC_ADDR(prP2pConnReq->aucDeviceID, prP2pDevDesc->aucDeviceAddr); + + prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod; + + if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) { + prP2pConnReq->fgIsPersistentGroup = FALSE; + prP2pConnReq->fgIsTobeGO = FALSE; + + } + + else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) { + DBGLOG(P2P, TRACE, ("Re-invoke Persistent Group\n")); + prP2pConnReq->fgIsPersistentGroup = TRUE; + prP2pConnReq->fgIsTobeGO = (prGlueInfo->prP2PInfo->ucRole == 2)?TRUE:FALSE; + + } + + + p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL); + + if (ucOperatingChnl != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = ucOperatingChnl; + } + + if ((ucSsidLen < 32) && (pucSsid != NULL)) { + COPY_SSID(prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen, + pucSsid, + ucSsidLen); + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T)prP2pConnReq, + MSG_SEND_METHOD_BUF); + + + + } while (FALSE); + + // frog add. + // TODO: Invitation Indication + + return; +#endif + +} /* kalP2PInvitationIndication */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an status to supplicant for device invitation status. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationStatus ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4InvStatus + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4InvStatus = u4InvStatus; + + // prepare event structure + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_INV_STATUS"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* kalP2PInvitationStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PIndicateSDRequest( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucSeqNum + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_SD_REQ %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* end of kalP2PIndicateSDRequest() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery response +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void +kalP2PIndicateSDResponse( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucSeqNum + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_SD_RESP %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* end of kalP2PIndicateSDResponse() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery TX Done +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] ucSeqNum Sequence number of the frame +* \param[in] ucStatus Status code for TX +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PIndicateTXDone( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucSeqNum, + IN UINT_8 ucStatus + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + + return; +} /* end of kalP2PIndicateSDResponse() */ + + +struct net_device* +kalP2PGetDevHdlr( + P_GLUE_INFO_T prGlueInfo + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + return prGlueInfo->prP2PInfo->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PIndicateSecCheckRsp ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucRsp, + IN UINT_16 u2RspLen + ) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_SEC_CHECK_RSP="); + + kalMemCopy(prGlueInfo->prP2PInfo->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, + IWEVCUSTOM, + &evt, + aucBuffer); + return; +} /* p2pFsmRunEventRxDisassociation */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChnlList( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, + IN PUINT_8 pucNumOfChannel, + IN P_RF_CHANNEL_INFO_T paucChannelList + ) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + eSpecificBand, + ucMaxChannelNum, + pucNumOfChannel, + paucChannelList); +} /* kalGetChnlList */ + +//////////////////////////////////////ICS SUPPORT////////////////////////////////////// + +VOID +kalP2PIndicateChannelReady ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, + IN ENUM_CHNL_EXT_T eSco, + IN UINT_32 u4Duration + ) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) { + break; + } + + + kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo, &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + cfg80211_ready_on_channel(prGlueInfo->prP2PInfo->prDevHandler, //struct net_device * dev, + u8SeqNum, //u64 cookie, + prIEEE80211ChnlStruct, //struct ieee80211_channel * chan, + eChnlType, //enum nl80211_channel_type channel_type, + u4Duration, //unsigned int duration, + GFP_KERNEL); //gfp_t gfp /* allocation flags */ + + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +VOID +kalP2PIndicateChannelExpired ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ) +{ + + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + RF_CHANNEL_INFO_T rRfChannelInfo; + + do { + if ((prGlueInfo == NULL) || (prChnlReqInfo == NULL)) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + + DBGLOG(P2P, TRACE, ("kalP2PIndicateChannelExpired\n")); + + rRfChannelInfo.eBand = prChnlReqInfo->eBand; + rRfChannelInfo.ucChannelNum = prChnlReqInfo->ucReqChnlNum; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); + + + kalP2pFuncGetChannelType(prChnlReqInfo->eChnlSco, + &eChnlType); + + + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + prChnlReqInfo->u8Cookie, + prIEEE80211ChnlStruct, + eChnlType, + GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +VOID +kalP2PIndicateScanDone ( + IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgIsAbort + ) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + + if (prGlueP2pInfo->prScanRequest) { + cfg80211_scan_done(prGlueP2pInfo->prScanRequest, + fgIsAbort); + + prGlueP2pInfo->prScanRequest = NULL; + } + + } while (FALSE); + + +} /* kalP2PIndicateScanDone */ + +VOID +kalP2PIndicateBssInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, + IN P_RF_CHANNEL_INFO_T prChannelInfo, + IN INT_32 i4SignalStrength + ) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; + struct ieee80211_mgmt *prBcnProbeRspFrame = (struct ieee80211_mgmt *)pucFrameBuf; + struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (prChannelInfo == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + + prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, prChannelInfo); + + if (prChannelEntry == NULL) { + DBGLOG(P2P, TRACE, ("Unknown channel info\n")); + break; + } + + + //rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000; + + prCfg80211Bss = cfg80211_inform_bss_frame(prGlueP2pInfo->wdev.wiphy, //struct wiphy * wiphy, + prChannelEntry, + prBcnProbeRspFrame, + u4BufLen, + i4SignalStrength, + GFP_KERNEL); + + + /* Return this structure. */ + cfg80211_put_bss(prCfg80211Bss); + + } while (FALSE); + + return; + +} /* kalP2PIndicateBssInfo */ + +VOID +kalP2PIndicateMgmtTxStatus ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN BOOLEAN fgIsAck, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4FrameLen + ) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + + do { + if ((prGlueInfo == NULL) || + (pucFrameBuf == NULL) || + (u4FrameLen == 0)) { + DBGLOG(P2P, TRACE, ("Unexpected pointer PARAM. 0x%lx, 0x%lx, %ld.", prGlueInfo, pucFrameBuf, u4FrameLen)); + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + cfg80211_mgmt_tx_status(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + u8Cookie, + pucFrameBuf, + u4FrameLen, + fgIsAck, + GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +VOID +kalP2PIndicateRxMgmtFrame ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_SW_RFB_T prSwRfb + ) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 0 + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; +#if DBG_P2P_MGMT_FRAME_INDICATION + P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T)NULL; +#endif + + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; + +#if DBG_P2P_MGMT_FRAME_INDICATION + + prWlanHeader = (P_WLAN_MAC_HEADER_T)prSwRfb->pvHeader; + + switch (prWlanHeader->u2FrameCtrl) { + case MAC_FRAME_PROBE_REQ: + DBGLOG(P2P, TRACE, ("RX Probe Req at channel %d ", ucChnlNum)); + break; + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, ("RX Probe Rsp at channel %d ", ucChnlNum)); + break; + case MAC_FRAME_ACTION: + DBGLOG(P2P, TRACE, ("RX Action frame at channel %d ", ucChnlNum)); + break; + default: + DBGLOG(P2P, TRACE, ("RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum)); + break; + } + + DBGLOG(P2P, TRACE, ("from: "MACSTR"\n", MAC2STR(prWlanHeader->aucAddr2))); +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + i4Freq, + RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + i4Freq, + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +VOID +kalP2PGCIndicateConnectionStatus ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, + IN UINT_16 u2RxIELen, + IN UINT_16 u2StatusReason + ) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prP2pConnInfo) { + cfg80211_connect_result(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, + u2RxIELen, + u2StatusReason, + GFP_KERNEL); //gfp_t gfp /* allocation flags */ + prP2pConnInfo->fgIsConnRequest = FALSE; + } + else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->prDevHandler, //struct net_device * dev, + u2StatusReason, + pucRxIEBuf, + u2RxIELen, + GFP_KERNEL); + } + + + + } while (FALSE); + + +} /* kalP2PGCIndicateConnectionStatus */ + + +VOID +kalP2PGOStationUpdate ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_STA_RECORD_T prCliStaRec, + IN BOOLEAN fgIsNew + ) +{ + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T)NULL; + struct station_info rStationInfo; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL)) { + break; + } + + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (fgIsNew) { + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; +// rStationInfo.filled |= STATION_INFO_ASSOC_REQ_IES; + + cfg80211_new_sta(prGlueInfo->prP2PInfo->prDevHandler, //struct net_device * dev, + prCliStaRec->aucMacAddr, + &rStationInfo, + GFP_KERNEL); + } + else { + ++prP2pGlueInfo->i4Generation; + + cfg80211_del_sta(prGlueInfo->prP2PInfo->prDevHandler, //struct net_device * dev, + prCliStaRec->aucMacAddr, + GFP_KERNEL); + } + + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + + + + +BOOLEAN +kalP2pFuncGetChannelType( + IN ENUM_CHNL_EXT_T rChnlSco, + OUT enum nl80211_channel_type *channel_type + ) +{ + BOOLEAN fgIsValid = FALSE; + + do { + if (channel_type) { + + switch (rChnlSco) { + case CHNL_EXT_SCN: + *channel_type = NL80211_CHAN_NO_HT; + break; + case CHNL_EXT_SCA: + *channel_type = NL80211_CHAN_HT40MINUS; + break; + case CHNL_EXT_SCB: + *channel_type = NL80211_CHAN_HT40PLUS; + break; + default: + ASSERT(FALSE); + *channel_type = NL80211_CHAN_NO_HT; + break; + } + + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} /* kalP2pFuncGetChannelType */ + + + + +struct ieee80211_channel * +kalP2pFuncGetChannelEntry ( + IN P_GL_P2P_INFO_T prP2pInfo, + IN P_RF_CHANNEL_INFO_T prChannelInfo + ) +{ + struct ieee80211_channel *prTargetChannelEntry = (struct ieee80211_channel *)NULL; + UINT_32 u4TblSize = 0, u4Idx = 0; + + do { + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) { + break; + } + + + switch (prChannelInfo->eBand) { + case BAND_2G4: + prTargetChannelEntry = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]->channels; + u4TblSize = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels; + break; + case BAND_5G: + prTargetChannelEntry = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]->channels; + u4TblSize = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; + break; + default: + break; + } + + + if (prTargetChannelEntry == NULL) { + break; + } + + + + for (u4Idx = 0; u4Idx < u4TblSize; u4Idx++, prTargetChannelEntry++) { + if (prTargetChannelEntry->hw_value == prChannelInfo->ucChannelNum) { + break; + } + + } + + + if (u4Idx == u4TblSize) { + prTargetChannelEntry = NULL; + break; + } + + + } while (FALSE); + + return prTargetChannelEntry; +} /* kalP2pFuncGetChannelEntry */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the block list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalP2PSetBlackList ( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rbssid, + IN BOOLEAN fgIsblock + ) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + BOOLEAN fgIsValid = FALSE; + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if(fgIsblock) { + for(i = 0; i < 8; i++) { + if(UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if(UNEQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + if(EQUAL_MAC_ADDR (&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid); + fgIsValid = FALSE; + return fgIsValid; + } + } + } + } + } + else { + for(i = 0; i < 8; i++) { + if(EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr); + fgIsValid = FALSE; + return fgIsValid; + } + } + } + + return fgIsValid; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to compare the black list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalP2PCmpBlackList ( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rbssid + ) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + BOOLEAN fgIsExsit = FALSE; + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + for(i = 0; i < 8; i++) { + if(UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)){ + if(EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + fgIsExsit = TRUE; + return fgIsExsit; + } + } + } + + return fgIsExsit; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to return the max clients of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetMaxClients ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4MaxClient + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if(u4MaxClient == 0 || prGlueInfo->prP2PInfo->ucMaxClients >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo->ucMaxClients = P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo->ucMaxClients = u4MaxClient; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to return the max clients of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalP2PMaxClients ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4NumClient + ) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if(prGlueInfo->prP2PInfo->ucMaxClients) { + if((UINT_8)u4NumClient > prGlueInfo->prP2PInfo->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c new file mode 100755 index 000000000000..3e53176c8991 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c @@ -0,0 +1,811 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_proc.c#1 $ +*/ + +/*! \file "gl_proc.c" + \brief This file defines the interface which can interact with users in /proc fs. + + Detail description. +*/ + + + +/* +** $Log: gl_proc.c $ + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support +** \main\maintrunk.MT5921\19 2008-09-02 21:08:37 GMT mtk01461 +** Fix the compile error of SPRINTF() +** \main\maintrunk.MT5921\18 2008-08-10 18:48:28 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\17 2008-08-04 16:52:01 GMT mtk01461 +** Add proc dbg print message of DOMAIN_INDEX level +** \main\maintrunk.MT5921\16 2008-07-10 00:45:16 GMT mtk01461 +** Remove the check of MCR offset, we may use the MCR address which is not align to DW boundary or proprietary usage. +** \main\maintrunk.MT5921\15 2008-06-03 20:49:44 GMT mtk01461 +** \main\maintrunk.MT5921\14 2008-06-02 22:56:00 GMT mtk01461 +** Rename some functions for linux proc +** \main\maintrunk.MT5921\13 2008-06-02 20:23:18 GMT mtk01461 +** Revise PROC mcr read / write for supporting TELNET +** \main\maintrunk.MT5921\12 2008-03-28 10:40:25 GMT mtk01461 +** Remove temporary set desired rate in linux proc +** \main\maintrunk.MT5921\11 2008-01-07 15:07:29 GMT mtk01461 +** Add User Update Desired Rate Set for QA in Linux +** \main\maintrunk.MT5921\10 2007-12-11 00:11:14 GMT mtk01461 +** Fix SPIN_LOCK protection +** \main\maintrunk.MT5921\9 2007-12-04 18:07:57 GMT mtk01461 +** Add additional debug category to proc +** \main\maintrunk.MT5921\8 2007-11-02 01:03:23 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\7 2007-10-25 18:08:14 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +** Revision 1.3 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.2 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "gl_kal.h" + +#include "wlan_lib.h" +#include "debug.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PROC_MCR_ACCESS "mcr" +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL "dbg_level" + +#define PROC_MCR_ACCESS_MAX_USER_INPUT_LEN 20 +#define PROC_RX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_TX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_DBG_LEVEL_MAX_USER_INPUT_LEN 20 +#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN 30 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_32 u4McrOffset = 0; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading MCR register to User Space, the offset of +* the MCR is specified in u4McrOffset. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procMCRRead ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo; + PARAM_CUSTOM_MCR_RW_STRUC_T rMcrInfo; + UINT_32 u4BufLen; + char *p = page; + UINT_32 u4Count; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + + ASSERT(data); + + // Kevin: Apply PROC read method 1. + if (off != 0) { + return 0; // To indicate end of file. + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, + (PVOID)&rMcrInfo, + sizeof(rMcrInfo), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); + + + SPRINTF(p, ("MCR (0x%08lxh): 0x%08lx\n", + rMcrInfo.u4McrOffset, rMcrInfo.u4McrData)); + + u4Count = (UINT_32)(p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procMCRRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for writing MCR register to HW or update u4McrOffset +* for reading MCR later. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procMCRWrite ( + struct file *file, + const char *buffer, + unsigned long count, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo; + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; // + 1 for "\0" + int i4CopySize; + PARAM_CUSTOM_MCR_RW_STRUC_T rMcrInfo; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + + ASSERT(data); + + i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) { + return 0; + } + acBuf[i4CopySize] = '\0'; + + switch (sscanf(acBuf, "0x%lx 0x%lx", + &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData)) { + case 2: + /* NOTE: Sometimes we want to test if bus will still be ok, after accessing + * the MCR which is not align to DW boundary. + */ + //if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) + { + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + u4McrOffset = rMcrInfo.u4McrOffset; + + //printk("Write 0x%lx to MCR 0x%04lx\n", + //rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + (PVOID)&rMcrInfo, + sizeof(rMcrInfo), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + } + break; + + case 1: + //if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) + { + u4McrOffset = rMcrInfo.u4McrOffset; + } + break; + + default: + break; + } + + return count; + +} /* end of procMCRWrite() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver Status to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procDrvStatusRead ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(data); + + // Kevin: Apply PROC read method 1. + if (off != 0) { + return 0; // To indicate end of file. + } + + + SPRINTF(p, ("GLUE LAYER STATUS:")); + SPRINTF(p, ("\n==================")); + + SPRINTF(p, ("\n* Number of Pending Frames: %ld\n", + prGlueInfo->u4TxPendingFrameNum)); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryDrvStatusForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32)(p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procDrvStatusRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver RX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procRxStatisticsRead ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(data); + + // Kevin: Apply PROC read method 1. + if (off != 0) { + return 0; // To indicate end of file. + } + + + SPRINTF(p, ("RX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32)(p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procRxStatisticsRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver RX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procRxStatisticsWrite ( + struct file *file, + const char *buffer, + unsigned long count, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; // + 1 for "\0" + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, "%ld", &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetRxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procRxStatisticsWrite() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver TX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procTxStatisticsRead ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(data); + + // Kevin: Apply PROC read method 1. + if (off != 0) { + return 0; // To indicate end of file. + } + + + SPRINTF(p, ("TX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32)(p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procTxStatisticsRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver TX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procTxStatisticsWrite ( + struct file *file, + const char *buffer, + unsigned long count, + void *data + ) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; // + 1 for "\0" + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, "%ld", &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetTxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procTxStatisticsWrite() */ +#endif + + +#if DBG +static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "DBG_INIT_IDX", + "DBG_HAL_IDX", + "DBG_INTR_IDX", + "DBG_REQ_IDX", + "DBG_TX_IDX", + "DBG_RX_IDX", + "DBG_RFTEST_IDX", + "DBG_EMU_IDX", + "DBG_SW1_IDX", + "DBG_SW2_IDX", + "DBG_SW3_IDX", + "DBG_SW4_IDX", + "DBG_HEM_IDX", + "DBG_AIS_IDX", + "DBG_RLM_IDX", + "DBG_MEM_IDX", + "DBG_CNM_IDX", + "DBG_RSN_IDX", + "DBG_BSS_IDX", + "DBG_SCN_IDX", + "DBG_SAA_IDX", + "DBG_AAA_IDX", + "DBG_P2P_IDX", + "DBG_QM_IDX", + "DBG_SEC_IDX", + "DBG_BOW_IDX" + }; + +extern UINT_8 aucDebugModule[]; + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for displaying current Debug Level. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procDbgLevelRead ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data + ) +{ + char *p = page; + int i; + + + + // Kevin: Apply PROC read method 1. + if (off != 0) { + return 0; // To indicate end of file. + } + + for (i = 0; i < (sizeof(aucDbModuleName)/PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN); i++) { + SPRINTF(p, ("%c %-15s(0x%02x): %02x\n", + ((i == u4DebugModule) ? '*' : ' '), + &aucDbModuleName[i][0], + i, + aucDebugModule[i])); + } + + *eof = 1; + return (int)(p - page); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for adjusting Debug Level to turn on/off debugging message. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int +procDbgLevelWrite ( + struct file *file, + const char *buffer, + unsigned long count, + void *data + ) +{ + char acBuf[PROC_DBG_LEVEL_MAX_USER_INPUT_LEN + 1]; // + 1 for "\0" + UINT_32 u4CopySize; + UINT_32 u4NewDbgModule, u4NewDbgLevel; + + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, "0x%lx 0x%lx", &u4NewDbgModule, &u4NewDbgLevel) == 2) { + if (u4NewDbgModule < DBG_MODULE_NUM) { + u4DebugModule = u4NewDbgModule; + u4NewDbgLevel &= DBG_CLASS_MASK; + aucDebugModule[u4DebugModule] = (UINT_8)u4NewDbgLevel; + } + } + + return count; +} +#endif /* DBG */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function create a PROC fs in linux /proc/net subdirectory. +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 +procInitProcfs ( + struct net_device *prDev, + char *pucDevName + ) +{ + P_GLUE_INFO_T prGlueInfo; + struct proc_dir_entry *prEntry; + + + ASSERT(prDev); + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, ("init proc fs fail: proc_net == NULL\n")); + return -ENOENT; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (!prGlueInfo) { + DBGLOG(INIT, WARN, ("The OS context is NULL\n")); + return -ENOENT; + } + + + /* + /proc/net/wlan0 + |-- mcr (PROC_MCR_ACCESS) + |-- status (PROC_DRV_STATUS) + |-- rx_statistics (PROC_RX_STATISTICS) + |-- tx_statistics (PROC_TX_STATISTICS) + |-- dbg_level (PROC_DBG_LEVEL) + |-- (end) + */ + + /* + * Directory: Root (/proc/net/wlan0) + */ + + prGlueInfo->pProcRoot = proc_mkdir(pucDevName, init_net.proc_net); + if (prGlueInfo->pProcRoot == NULL) { + return -ENOENT; + } + + /* File Root/mcr (RW) */ + prEntry = create_proc_entry(PROC_MCR_ACCESS, 0, prGlueInfo->pProcRoot); + if (prEntry) { + prEntry->read_proc = procMCRRead; + prEntry->write_proc = procMCRWrite; + prEntry->data = (void *)prDev; + } + +#if 0 + /* File Root/status (RW) */ + prEntry = create_proc_read_entry(PROC_DRV_STATUS, 0, prGlueInfo->pProcRoot, + procDrvStatusRead, prDev); + + /* File Root/rx_statistics (RW) */ + prEntry = create_proc_entry(PROC_RX_STATISTICS, 0, prGlueInfo->pProcRoot); + if (prEntry) { + prEntry->read_proc = procRxStatisticsRead; + prEntry->write_proc = procRxStatisticsWrite; + prEntry->data = (void *)prDev; + } + + /* File Root/tx_statistics (RW) */ + prEntry = create_proc_entry(PROC_TX_STATISTICS, 0, prGlueInfo->pProcRoot); + if (prEntry) { + prEntry->read_proc = procTxStatisticsRead; + prEntry->write_proc = procTxStatisticsWrite; + prEntry->data = (void *)prDev; + } + +#if DBG + /* File Root/dbg_level (RW) */ + prEntry = create_proc_entry(PROC_DBG_LEVEL, 0644, prGlueInfo->pProcRoot); + if (prEntry) { + prEntry->read_proc = procDbgLevelRead; + prEntry->write_proc = procDbgLevelWrite; + } +#endif /* DBG */ +#endif + return 0; + +} /* end of procInitProcfs() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clean up a PROC fs created by procInitProcfs(). +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 +procRemoveProcfs ( + struct net_device *prDev, + char *pucDevName + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + + ASSERT(prDev); + + if (!prDev) { + return -ENOENT; + } + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, ("remove proc fs fail: proc_net == NULL\n")); + return -ENOENT; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo->pProcRoot) { + DBGLOG(INIT, WARN, ("The procfs root is NULL\n")); + return -ENOENT; + } +#if 0 +#if DBG + remove_proc_entry(PROC_DBG_LEVEL, prGlueInfo->pProcRoot); +#endif /* DBG */ + remove_proc_entry(PROC_TX_STATISTICS, prGlueInfo->pProcRoot); + remove_proc_entry(PROC_RX_STATISTICS, prGlueInfo->pProcRoot); + remove_proc_entry(PROC_DRV_STATUS, prGlueInfo->pProcRoot); +#endif + remove_proc_entry(PROC_MCR_ACCESS, prGlueInfo->pProcRoot); + + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry(pucDevName, init_net.proc_net); + + return 0; + +} /* end of procRemoveProcfs() */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c new file mode 100755 index 000000000000..eadc2c610cc6 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c @@ -0,0 +1,473 @@ +/* +** $Id: @(#) gl_rst.c@@ +*/ + +/*! \file gl_rst.c + \brief Main routines for supporintg MT6620 whole-chip reset mechanism + + This file contains the support routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + + + +/* +** $Log: gl_rst.c $ + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 04 22 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * skip power-off handshaking when RESET indication is received. + * + * 04 14 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected + * 2. add dummy function for both Win32 and Linux part. + * + * 03 30 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * use netlink unicast instead of broadcast + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include + +#if CFG_CHIP_RESET_SUPPORT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_BIND_PROCESS (4) + +#define MTK_WIFI_FAMILY_NAME "MTK_WIFI" +#define MTK_WIFI_RESET_START_NAME "RESET_START" +#define MTK_WIFI_RESET_END_NAME "RESET_END" +#define MTK_WIFI_RESET_TEST_NAME "GENETLINK_START" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum { + __MTK_WIFI_ATTR_INVALID, + MTK_WIFI_ATTR_MSG, + __MTK_WIFI_ATTR_MAX, +}; +#define MTK_WIFI_ATTR_MAX (__MTK_WIFI_ATTR_MAX - 1) + + +enum { + __MTK_WIFI_COMMAND_INVALID, + MTK_WIFI_COMMAND_BIND, + MTK_WIFI_COMMAND_RESET, + __MTK_WIFI_COMMAND_MAX, +}; +#define MTK_WIFI_COMMAND_MAX (__MTK_WIFI_COMMAND_MAX - 1) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/BOOLEAN fgIsResetting = FALSE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_32 mtk_wifi_seqnum = 0; +static int num_bind_process = 0; +static pid_t bind_pid[MAX_BIND_PROCESS]; + + +/* attribute policy */ +static struct nla_policy mtk_wifi_genl_policy[MTK_WIFI_ATTR_MAX + 1] = { + [MTK_WIFI_ATTR_MSG] = { .type = NLA_NUL_STRING }, +}; + +/* family definition */ +static struct genl_family mtk_wifi_gnl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = MTK_WIFI_FAMILY_NAME, + .version = 1, + .maxattr = MTK_WIFI_ATTR_MAX, +}; + +/* forward declaration */ +static int mtk_wifi_bind( + struct sk_buff *skb, + struct genl_info *info + ); + +static int mtk_wifi_reset( + struct sk_buff *skb, + struct genl_info *info + ); + +/* operation definition */ +static struct genl_ops mtk_wifi_gnl_ops_bind = { + .cmd = MTK_WIFI_COMMAND_BIND, + .flags = 0, + .policy = mtk_wifi_genl_policy, + .doit = mtk_wifi_bind, + .dumpit = NULL, +}; + +static struct genl_ops mtk_wifi_gnl_ops_reset = { + .cmd = MTK_WIFI_COMMAND_RESET, + .flags = 0, + .policy = mtk_wifi_genl_policy, + .doit = mtk_wifi_reset, + .dumpit = NULL, +}; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +extern int +mtk_wcn_wmt_msgcb_reg( + ENUM_WMTDRV_TYPE_T eType, + PF_WMT_CB pCb); + +extern int +mtk_wcn_wmt_msgcb_unreg( + ENUM_WMTDRV_TYPE_T eType + ); + +static void * +glResetCallback ( + ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, + void * prMsgBody, + unsigned int u4MsgLength + ); + +static BOOLEAN +glResetSendMessage ( + char *aucMsg, + u8 cmd + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. registering for reset callbacks + * 2. initialize netlink socket + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID +glResetInit( + VOID + ) +{ + /* 1. register for reset callback */ + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB)glResetCallback); + + /* 2.1 registration for NETLINK_GENERIC family */ + if(genl_register_family(&mtk_wifi_gnl_family) != 0) { + DBGLOG(INIT, WARN, ("%s(): GE_NELINK family registration fail\n", __func__)); + } + else { + /* 2.2 operation registration */ + if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_bind) != 0) { + DBGLOG(INIT, WARN, ("%s(): BIND operation registration fail\n", __func__)); + } + + if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_reset) != 0) { + DBGLOG(INIT, WARN, ("%s(): RESET operation registration fail\n", __func__)); + } + } + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. uninitialize netlink socket + * 2. deregistering for reset callbacks + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID +glResetUninit( + VOID + ) +{ + /* 1. release NETLINK_GENERIC family */ + genl_unregister_family(&mtk_wifi_gnl_family); + + /* 2. deregister for reset callback */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); + + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void * +glResetCallback ( + ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, + void * prMsgBody, + unsigned int u4MsgLength + ) +{ + switch(eMsgType) { + case WMTMSG_TYPE_RESET: + if(u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody; + + switch(*prRstMsg) { + case WMTRSTMSG_RESET_START: + fgIsResetting = TRUE; + glResetSendMessage(MTK_WIFI_RESET_START_NAME, MTK_WIFI_COMMAND_RESET); + break; + + case WMTRSTMSG_RESET_END: + glResetSendMessage(MTK_WIFI_RESET_END_NAME, MTK_WIFI_COMMAND_RESET); + fgIsResetting = FALSE; + break; + + default: + break; + } + } + + break; + + default: + break; + } + + return NULL; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine send out message via netlink socket + * + * @param aucMsg + * u4MsgLength + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +glResetSendMessage( + char * aucMsg, + u8 cmd + ) +{ + struct sk_buff *skb = NULL; + void *msg_head = NULL; + int rc = -1; + int i; + + if(num_bind_process == 0) { + /* no listening process */ + return FALSE; + } + + for(i = 0 ; i < num_bind_process ; i++) { + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + + if(skb) { + msg_head = genlmsg_put(skb, 0, mtk_wifi_seqnum++, &mtk_wifi_gnl_family, 0, cmd); + + if(msg_head == NULL) { + nlmsg_free(skb); + return FALSE; + } + + rc = nla_put_string(skb, MTK_WIFI_ATTR_MSG, aucMsg); + if(rc != 0) { + nlmsg_free(skb); + return FALSE; + } + + /* finalize the message */ + genlmsg_end(skb, msg_head); + + /* sending message */ + rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); + if(rc != 0) { + return FALSE; + } + } + else { + return FALSE; + } + } + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called to identify PID for process binding + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +int mtk_wifi_bind( + struct sk_buff *skb, + struct genl_info *info + ) +{ + struct nlattr *na; + char * mydata; + + if (info == NULL) { + goto out; + } + + /*for each attribute there is an index in info->attrs which points to a nlattr structure + *in this structure the data is given + */ + + na = info->attrs[MTK_WIFI_ATTR_MSG]; + if (na) { + mydata = (char *)nla_data(na); + + /* no need to parse mydata */ + } + + /* collect PID */ + if(num_bind_process < MAX_BIND_PROCESS) { + bind_pid[num_bind_process] = info->snd_pid; + num_bind_process++; + } + else { + DBGLOG(INIT, WARN, ("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS)); + } + +out: + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for reset, shout not happen + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +int mtk_wifi_reset( + struct sk_buff *skb, + struct genl_info *info + ) +{ + DBGLOG(INIT, WARN, ("%s(): should not be invoked\n", __func__)); + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +VOID +glSendResetRequest( + VOID + ) +{ + // WMT thread would trigger whole chip resetting itself + return; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if MT6620 is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalIsResetting( + VOID + ) +{ + return fgIsResetting; +} + + +#endif // CFG_CHIP_RESET_SUPPORT diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c new file mode 100755 index 000000000000..17e3460a6a48 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c @@ -0,0 +1,4527 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#3 $ +*/ + +/*! \file gl_wext.c + \brief ioctl() (mostly Linux Wireless Extensions) routines for STA driver. +*/ + + + +/* +** $Log: gl_wext.c $ + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 23 2011 tsaiyuan.hsu + * [WCXRP00000979] [MT6620 Wi-Fi][DRV]] stop attempting to connect to config AP after D3 state + * avoid entering D3 state after deep sleep. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 27 2011 wh.su + * [WCXRP00000877] [MT6620 Wi-Fi][Driver] Remove the netif_carry_ok check for avoid the wpa_supplicant fail to query the ap address + * Remove the netif check while query bssid and ssid + * + * 07 26 2011 chinglan.wang + * NULL + * [MT6620][WiFi Driver] Do not include the WSC IE in the association info packet when not do the wps connection.. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 17 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Initilize the vairlabes. + * + * 05 11 2011 jeffrey.chang + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * modify set_tx_pow ioctl + * + * 03 29 2011 terry.wu + * [WCXRP00000610] [MT 6620 Wi-Fi][Driver] Fix klocwork waring + * [MT6620 Wi-Fi][Driver] Fix klocwork warning. Add Null pointer check on wext_get_essid. Limit the upper bound of essid storage array. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 02 21 2011 wh.su + * [WCXRP00000483] [MT6620 Wi-Fi][Driver] Check the kalIoctl return value before doing the memory copy at linux get essid + * fixed the potential error to do a larget memory copy while wlanoid get essid not actually running. + * + * 02 08 2011 george.huang + * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler + * Support querying power mode OID. + * + * 01 29 2011 wh.su + * [WCXRP00000408] [MT6620 Wi-Fi][Driver] Not doing memory alloc while ioctl set ie with length 0 + * not doing mem alloc. while set ie length already 0 + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Remove debug text. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Adjust OID order. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. . + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous types + * to ease slab system pressure + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Support set PS profile and set WMM-PS related iwpriv. + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Allow change PS profile function (throught wext_set_power()). + * + * 12 14 2010 jeffrey.chang + * [WCXRP00000262] [MT6620 Wi-Fi][Driver] modify the scan request ioctl to handle hidden SSID + * handle hidden SSID + * + * 12 13 2010 chinglan.wang + * NULL + * Add WPS 1.0 feature flag to enable the WPS 1.0 function. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * Fix compiling error + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 30 2010 cp.wu + * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 + * . + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000121] [MT6620 Wi-Fi][Driver] Temporarily disable set power mode ioctl which may cause 6620 to enter power saving + * Temporarily disable set power mode ioctl which may cause MT6620 to enter power saving + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue + * refine the scan ioctl to prevent hanging of Android UI + * + * 10 01 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * add the scan result with wapi ie. + * + * 09 30 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * fixed the wapi ie assigned issue. + * + * 09 27 2010 wh.su + * NULL + * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 09 2010 cp.wu + * NULL + * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 02 2010 jeffrey.chang + * NULL + * enable remove key ioctl + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) enable encyption ioctls + * 2) temporarily disable remove keys ioctl to prevent TX1 busy + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * for linux driver migration + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove unused macro and debug messages + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add dissassoication support for wpa supplicant + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add ioctl of power management + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug message + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used + * * 2) fix ioctl + * + * 04 12 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug messages for pre-release + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * are done in adapter layer. + * + * 04 02 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl type + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * enable pmksa cache operation + * + * 03 31 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl which may cause cmdinfo memory leak + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\38 2009-10-08 10:33:22 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers. +** \main\maintrunk.MT5921\37 2009-09-29 16:49:48 GMT mtk01090 +** Remove unused variables +** \main\maintrunk.MT5921\36 2009-09-28 20:19:11 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\35 2009-09-03 11:42:30 GMT mtk01088 +** adding the wapi ioctl support +** \main\maintrunk.MT5921\34 2009-08-18 22:56:50 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\33 2009-05-14 22:43:47 GMT mtk01089 +** fix compiling warning +** \main\maintrunk.MT5921\32 2009-05-07 22:26:18 GMT mtk01089 +** Add mandatory and private IO control for Linux BWCS +** \main\maintrunk.MT5921\31 2009-02-07 15:11:14 GMT mtk01088 +** fixed the compiling error +** \main\maintrunk.MT5921\30 2009-02-07 14:46:51 GMT mtk01088 +** add the privacy setting from linux supplicant ap selection +** \main\maintrunk.MT5921\29 2008-11-19 15:18:50 GMT mtk01088 +** fixed the compling error +** \main\maintrunk.MT5921\28 2008-11-19 11:56:18 GMT mtk01088 +** rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\27 2008-08-29 16:59:43 GMT mtk01088 +** fixed compiling error +** \main\maintrunk.MT5921\26 2008-08-29 14:55:53 GMT mtk01088 +** adjust the code for meet the coding style, and add assert check +** \main\maintrunk.MT5921\25 2008-06-02 11:15:19 GMT mtk01461 +** Update after wlanoidSetPowerMode changed +** \main\maintrunk.MT5921\24 2008-05-30 15:13:12 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\23 2008-03-28 10:40:28 GMT mtk01461 +** Add set desired rate in Linux STD IOCTL +** \main\maintrunk.MT5921\22 2008-03-18 10:31:24 GMT mtk01088 +** add pmkid ioctl and indicate +** \main\maintrunk.MT5921\21 2008-03-11 15:21:24 GMT mtk01461 +** \main\maintrunk.MT5921\20 2008-03-11 14:50:55 GMT mtk01461 +** Refine WPS related priv ioctl for unified interface +** +** \main\maintrunk.MT5921\19 2008-03-06 16:30:41 GMT mtk01088 +** move the configuration code from set essid function, +** remove the non-used code +** \main\maintrunk.MT5921\18 2008-02-21 15:47:09 GMT mtk01461 +** Fix CR[489] +** \main\maintrunk.MT5921\17 2008-02-12 23:38:31 GMT mtk01461 +** Add Set Frequency & Channel oid support for Linux +** \main\maintrunk.MT5921\16 2008-01-24 12:07:34 GMT mtk01461 +** \main\maintrunk.MT5921\15 2008-01-24 12:00:10 GMT mtk01461 +** Modify the wext_essid for set up correct information for IBSS, and fix the wrong input ptr for prAdapter +** \main\maintrunk.MT5921\14 2007-12-06 09:30:12 GMT mtk01425 +** 1. Branch Test +** \main\maintrunk.MT5921\13 2007-12-04 18:07:59 GMT mtk01461 +** fix typo +** \main\maintrunk.MT5921\12 2007-11-30 17:10:21 GMT mtk01425 +** 1. Fix compiling erros +** +** \main\maintrunk.MT5921\11 2007-11-27 10:43:22 GMT mtk01425 +** 1. Add WMM-PS setting +** \main\maintrunk.MT5921\10 2007-11-06 20:33:32 GMT mtk01088 +** fixed the compiler error +** \main\maintrunk.MT5921\9 2007-11-06 19:33:15 GMT mtk01088 +** add WPS code +** \main\maintrunk.MT5921\8 2007-10-30 12:00:44 GMT MTK01425 +** 1. Update wlanQueryInformation +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \ + switch (ch) \ + { \ + case 1: khz = 2412000; break; \ + case 2: khz = 2417000; break; \ + case 3: khz = 2422000; break; \ + case 4: khz = 2427000; break; \ + case 5: khz = 2432000; break; \ + case 6: khz = 2437000; break; \ + case 7: khz = 2442000; break; \ + case 8: khz = 2447000; break; \ + case 9: khz = 2452000; break; \ + case 10: khz = 2457000; break; \ + case 11: khz = 2462000; break; \ + case 12: khz = 2467000; break; \ + case 13: khz = 2472000; break; \ + case 14: khz = 2484000; break; \ + case 36: /* UNII */ khz = 5180000; break; \ + case 40: /* UNII */ khz = 5200000; break; \ + case 44: /* UNII */ khz = 5220000; break; \ + case 48: /* UNII */ khz = 5240000; break; \ + case 52: /* UNII */ khz = 5260000; break; \ + case 56: /* UNII */ khz = 5280000; break; \ + case 60: /* UNII */ khz = 5300000; break; \ + case 64: /* UNII */ khz = 5320000; break; \ + case 149: /* UNII */ khz = 5745000; break; \ + case 153: /* UNII */ khz = 5765000; break; \ + case 157: /* UNII */ khz = 5785000; break; \ + case 161: /* UNII */ khz = 5805000; break; \ + case 165: /* UNII */ khz = 5825000; break; \ + case 100: /* HiperLAN2 */ khz = 5500000; break; \ + case 104: /* HiperLAN2 */ khz = 5520000; break; \ + case 108: /* HiperLAN2 */ khz = 5540000; break; \ + case 112: /* HiperLAN2 */ khz = 5560000; break; \ + case 116: /* HiperLAN2 */ khz = 5580000; break; \ + case 120: /* HiperLAN2 */ khz = 5600000; break; \ + case 124: /* HiperLAN2 */ khz = 5620000; break; \ + case 128: /* HiperLAN2 */ khz = 5640000; break; \ + case 132: /* HiperLAN2 */ khz = 5660000; break; \ + case 136: /* HiperLAN2 */ khz = 5680000; break; \ + case 140: /* HiperLAN2 */ khz = 5700000; break; \ + case 34: /* Japan MMAC */ khz = 5170000; break; \ + case 38: /* Japan MMAC */ khz = 5190000; break; \ + case 42: /* Japan MMAC */ khz = 5210000; break; \ + case 46: /* Japan MMAC */ khz = 5230000; break; \ + case 184: /* Japan */ khz = 4920000; break; \ + case 188: /* Japan */ khz = 4940000; break; \ + case 192: /* Japan */ khz = 4960000; break; \ + case 196: /* Japan */ khz = 4980000; break; \ + case 208: /* Japan, means J08 */ khz = 5040000; break; \ + case 212: /* Japan, means J12 */ khz = 5060000; break; \ + case 216: /* Japan, means J16 */ khz = 5080000; break; \ + default: khz = 2412000; break; \ + } \ + } + + +#define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0])) + +#define MAX_SSID_LEN 32 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* NOTE: name in iwpriv_args only have 16 bytes */ +static const struct iw_priv_args rIwPrivTable[] = { + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, ""}, + + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + + {IOCTL_SET_INTS, IW_PRIV_TYPE_INT | 4, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | 50, ""}, + + /* added for set_oid and get_oid */ + {IOCTL_SET_STRUCT, 256, 0, ""}, + {IOCTL_GET_STRUCT, 0, 256, ""}, + + /* sub-ioctl definitions */ +#if 0 + {PRIV_CMD_REG_DOMAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_reg_domain" }, + {PRIV_CMD_REG_DOMAIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_reg_domain" }, +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {PRIV_CMD_CSUM_OFFLOAD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_tcp_csum" }, +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + {PRIV_CMD_POWER_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power_mode" }, + {PRIV_CMD_POWER_MODE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_power_mode" }, + + {PRIV_CMD_WMM_PS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_wmm_ps" }, + + {PRIV_CMD_TEST_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_test_mode" }, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_test_cmd" }, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_test_result" }, +#if CFG_SUPPORT_PRIV_MCR_RW + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_mcr" }, + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mcr" }, +#endif + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl" }, + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_sw_ctrl" }, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs"}, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band" }, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band" }, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower" }, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list" }, + {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem" }, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode" }, +#endif +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, +}; + +const struct iw_handler_def wext_handler_def = { + .num_standard = 0, + .num_private = (__u16)sizeof(rIwPrivHandler)/sizeof(iw_handler), + .num_private_args = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args), + .standard = (iw_handler *) NULL, + .private = rIwPrivHandler, + .private_args = rIwPrivTable, + .get_wireless_stats = wext_get_wireless_stats, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPA/RSN Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPAIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + else { + /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + } /* check EID == 0xDD */ + } /* check desired EID */ + + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WAPI Information Element . +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWAPIIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + OUT PUINT_8 *ppucDesiredIE + ) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } /* check desired EID */ + + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredWAPIIE */ +#endif + + +#if CFG_SUPPORT_WPS +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPS Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPSIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + else { + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + } /* check EID == 0xDD */ + } /* check desired EID */ + + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the name of the protocol used on the air. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] pcName Buffer to store protocol name string +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note If netif_carrier_ok, protocol name is returned; +* otherwise, "disconnected" is returned. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT char *pcName, + IN char *pcExtra + ) +{ + ENUM_PARAM_NETWORK_TYPE_T eNetWorkType; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (netif_carrier_ok(prNetDev)) { + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNetworkTypeInUse, + &eNetWorkType, + sizeof(eNetWorkType), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + switch(eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strcpy(pcName, "IEEE 802.11b"); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strcpy(pcName, "IEEE 802.11bgn"); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strcpy(pcName, "IEEE 802.11abgn"); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strcpy(pcName, "IEEE 802.11"); + break; + } + } + else { + strcpy(pcName, "Disconnected"); + } + + return 0; +} /* wext_get_name */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set the operating channel in the wireless device. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL +* \param[in] prFreq Buffer to store frequency information +* \param[in] pcExtra NULL +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If infrastructure mode is not NET NET_TYPE_IBSS. +* \retval -EINVAL Invalid channel frequency. +* +* \note If infrastructure mode is IBSS, new channel frequency is set to device. +* The range of channel number depends on different regulatory domain. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_freq ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN struct iw_freq *prIwFreq, + IN char *pcExtra + ) +{ + +#if 0 + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + printk("set m:%d, e:%d, i:%d, flags:%d\n", + prIwFreq->m, prIwFreq->e, prIwFreq->i, prIwFreq->flags); + */ + + /* If setting by frequency, convert to a channel */ + if ((prIwFreq->e == 1) && + (prIwFreq->m >= (int) 2.412e8) && + (prIwFreq->m <= (int) 2.484e8)) { + + /* Change to KHz format */ + u4ChnlFreq = (UINT_32)(prIwFreq->m / (KILO / 10)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, + sizeof(u4ChnlFreq), + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (WLAN_STATUS_SUCCESS != rStatus) { + return -EINVAL; + } + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) { + return -EOPNOTSUPP; + } + else { + /* Change to channel number format */ + u4ChnlFreq = (UINT_32)prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChannel, + &u4ChnlFreq, + sizeof(u4ChnlFreq), + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + + if (WLAN_STATUS_SUCCESS != rStatus) { + return -EINVAL; + } + } + +#endif + + return 0; + +} /* wext_set_freq */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the operating channel in the wireless device. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prFreq Buffer to store frequency information. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise +* +* \note If netif_carrier_ok, channel frequency information is stored in pFreq. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_freq ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_freq *prIwFreq, + IN char *pcExtra + ) +{ + UINT_32 u4Channel = 0; + + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* GeorgeKuo: TODO skip checking in IBSS mode */ + if (!netif_carrier_ok(prNetDev)) { + return -ENOTCONN; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryFrequency, + &u4Channel, + sizeof(u4Channel), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + prIwFreq->m = (int) u4Channel; /* freq in KHz */ + prIwFreq->e = 3; + + return 0; + +} /* wext_get_freq */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set operating mode. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] pu4Mode Pointer to new operation mode. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If new mode is not supported. +* +* \note Device will run in new operation mode if it is valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_mode ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN unsigned int *pu4Mode, + IN char *pcExtra + ) +{ + ENUM_PARAM_OP_MODE_T eOpMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + switch (*pu4Mode) { + case IW_MODE_AUTO: + eOpMode = NET_TYPE_AUTO_SWITCH; + break; + + case IW_MODE_ADHOC: + eOpMode = NET_TYPE_IBSS; + break; + + case IW_MODE_INFRA: + eOpMode = NET_TYPE_INFRA; + break; + + default: + DBGLOG(INIT, INFO, ("%s(): Set UNSUPPORTED Mode = %d.\n", __FUNCTION__, *pu4Mode)); + return -EOPNOTSUPP; + } + + //printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, + sizeof(eOpMode), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} /* wext_set_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get operating mode. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo NULL. +* \param[out] pu4Mode Buffer to store operating mode information. +* \param[in] pcExtra NULL. +* +* \retval 0 If data is valid. +* \retval -EINVAL Otherwise. +* +* \note If netif_carrier_ok, operating mode information is stored in pu4Mode. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_mode ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + OUT unsigned int *pu4Mode, + IN char *pcExtra + ) +{ + ENUM_PARAM_OP_MODE_T eOpMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryInfrastructureMode, + &eOpMode, + sizeof(eOpMode), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + switch (eOpMode){ + case NET_TYPE_IBSS: + *pu4Mode = IW_MODE_ADHOC; + break; + + case NET_TYPE_INFRA: + *pu4Mode = IW_MODE_INFRA; + break; + + case NET_TYPE_AUTO_SWITCH: + *pu4Mode = IW_MODE_AUTO; + break; + + default: + DBGLOG(INIT, INFO, ("%s(): Get UNKNOWN Mode.\n", __FUNCTION__)); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the valid range for each configurable STA setting value. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer to iw_point structure, not used. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 If data is valid. +* +* \note The extra buffer (pcExtra) is filled with information from driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prData, + OUT char *pcExtra + ) +{ + struct iw_range *prRange = NULL; + PARAM_RATES_EX aucSuppRate = {0}; /* data buffers */ + int i = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prRange = (struct iw_range *) pcExtra; + + memset(prRange, 0, sizeof(*prRange)); + prRange->throughput = 20000000; /* 20Mbps */ + prRange->min_nwid = 0; /* not used */ + prRange->max_nwid = 0; /* not used */ + + /* scan_capa not implemented */ + + /* event_capa[6]: kernel + driver capabilities */ + prRange->event_capa[0] = (IW_EVENT_CAPA_K_0 + | IW_EVENT_CAPA_MASK(SIOCGIWAP) + | IW_EVENT_CAPA_MASK(SIOCGIWSCAN) + /* can't display meaningful string in iwlist + | IW_EVENT_CAPA_MASK(SIOCGIWTXPOW) + | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE) + | IW_EVENT_CAPA_MASK(IWEVASSOCREQIE) + | IW_EVENT_CAPA_MASK(IWEVPMKIDCAND) + */ + ); + prRange->event_capa[1] = IW_EVENT_CAPA_K_1; + + /* report 2.4G channel and frequency only */ + prRange->num_channels = (__u16) NUM_CHANNELS; + prRange->num_frequency = (__u8) NUM_CHANNELS; + for (i = 0; i < NUM_CHANNELS; i++) { + /* iwlib takes this number as channel number */ + prRange->freq[i].i = i + 1; + prRange->freq[i].m = channel_freq[i]; + prRange->freq[i].e = 6; /* Values in table in MHz */ + } + + rStatus = kalIoctl( + prGlueInfo, + wlanoidQuerySupportedRates, + &aucSuppRate, + sizeof(aucSuppRate), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + for (i = 0; i < IW_MAX_BITRATES && i < PARAM_MAX_LEN_RATES_EX ; i++) { + if (aucSuppRate[i] == 0) { + break; + } + prRange->bitrate[i] = (aucSuppRate[i] & 0x7F) * 500000; /* 0.5Mbps */ + } + prRange->num_bitrates = i; + + prRange->min_rts = 0; + prRange->max_rts = 2347; + prRange->min_frag = 256; + prRange->max_frag = 2346; + + prRange->min_pmp = 0; /* power management by driver */ + prRange->max_pmp = 0; /* power management by driver */ + prRange->min_pmt = 0; /* power management by driver */ + prRange->max_pmt = 0; /* power management by driver */ + prRange->pmp_flags = IW_POWER_RELATIVE; /* pm default flag */ + prRange->pmt_flags = IW_POWER_ON; /* pm timeout flag */ + prRange->pm_capa = IW_POWER_ON; /* power management by driver */ + + prRange->encoding_size[0] = 5; /* wep40 */ + prRange->encoding_size[1] = 16; /* tkip */ + prRange->encoding_size[2] = 16; /* ckip */ + prRange->encoding_size[3] = 16; /* ccmp */ + prRange->encoding_size[4] = 13; /* wep104 */ + prRange->encoding_size[5] = 16; /* wep128 */ + prRange->num_encoding_sizes = 6; + prRange->max_encoding_tokens = 6; /* token? */ + +#if WIRELESS_EXT < 17 + prRange->txpower_capa = 0x0002; /* IW_TXPOW_RELATIVE */ +#else + prRange->txpower_capa = IW_TXPOW_RELATIVE; +#endif + prRange->num_txpower = 5; + prRange->txpower[0] = 0; /* minimum */ + prRange->txpower[1] = 25; /* 25% */ + prRange->txpower[2] = 50; /* 50% */ + prRange->txpower[3] = 100; /* 100% */ + + prRange->we_version_compiled = WIRELESS_EXT; + prRange->we_version_source = WIRELESS_EXT; + + prRange->retry_capa = IW_RETRY_LIMIT; + prRange->retry_flags = IW_RETRY_LIMIT; + prRange->min_retry = 7; + prRange->max_retry = 7; + prRange->r_time_flags = IW_RETRY_ON; + prRange->min_r_time = 0; + prRange->max_r_time = 0; + + /* signal strength and link quality */ + /* Just define range here, reporting value moved to wext_get_stats() */ + prRange->sensitivity = -83; /* fixed value */ + prRange->max_qual.qual = 100; /* max 100% */ + prRange->max_qual.level = (__u8)(0x100 - 0); /* max 0 dbm */ + prRange->max_qual.noise = (__u8)(0x100 - 0); /* max 0 dbm */ + + /* enc_capa */ +#if WIRELESS_EXT > 17 + prRange->enc_capa = IW_ENC_CAPA_WPA | + IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | + IW_ENC_CAPA_CIPHER_CCMP; +#endif + + /* min_pms; Minimal PM saving */ + /* max_pms; Maximal PM saving */ + /* pms_flags; How to decode max/min PM saving */ + + /* modul_capa; IW_MODUL_* bit field */ + /* bitrate_capa; Types of bitrates supported */ + + return 0; +} /* wext_get_range */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set BSSID of AP to connect. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prAddr Pointer to struct sockaddr structure containing AP's BSSID. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note Desired AP's BSSID is set to driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_ap ( + IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, + IN struct sockaddr *prAddr, + IN char *pcExtra + ) +{ + return 0; +} /* wext_set_ap */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get AP MAC address. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prAddr Pointer to struct sockaddr structure storing AP's BSSID. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, AP's mac address is stored in pAddr->sa_data. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_ap ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct sockaddr *prAddr, + IN char *pcExtra + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prAddr); + if (FALSE == GLUE_CHK_PR2(prNetDev, prAddr)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + //if (!netif_carrier_ok(prNetDev)) { + // return -ENOTCONN; + //} + + if(prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED){ + memset(prAddr, 0, 6); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssid, + prAddr->sa_data, + ETH_ALEN, + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + return 0; +} /* wext_get_ap */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set mlme operation request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer of iw_point header. +* \param[in] pcExtra Pointer to iw_mlme structure mlme request information. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP unsupported IW_MLME_ command. +* \retval -EINVAL Set MLME Fail, different bssid. +* +* \note Driver will start mlme operation if valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_mlme ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prData, + IN char *pcExtra + ) +{ + struct iw_mlme *prMlme = NULL; + + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prMlme = (struct iw_mlme *)pcExtra; + if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) { + if (!netif_carrier_ok(prNetDev)) { + DBGLOG(INIT, INFO, ("[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n")); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDisassociate, + NULL, + 0, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + return 0; + } + else { + DBGLOG(INIT, INFO, ("[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd)); + return -EOPNOTSUPP; + } +} /* wext_set_mlme */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To issue scan request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData NULL. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EFAULT Tx power is off. +* +* \note Device will start scanning. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_scan ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN union iwreq_data *prData, + IN char *pcExtra + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + int essid_len = 0; + + ASSERT(prNetDev); + if (FALSE == GLUE_CHK_DEV(prNetDev)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if WIRELESS_EXT > 17 + /* retrieve SSID */ + if(prData) { + essid_len = ((struct iw_scan_req *)(((struct iw_point*)prData)->pointer))->essid_len; + } +#endif + + init_completion(&prGlueInfo->rScanComp); + + // TODO: parse flags and issue different scan requests? + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScan, + pcExtra, + essid_len, + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + //wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 2 * KAL_HZ); + //kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + + + return 0; +} /* wext_set_scan */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To write the ie to buffer +* +*/ +/*----------------------------------------------------------------------------*/ +static inline int snprintf_hex(char *buf, size_t buf_size, const u8 *data, + size_t len) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + + if (buf_size == 0) + return 0; + + for (i = 0; i < len; i++) { + ret = snprintf(pos, end - pos, "%02x", + data[i]); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + end[-1] = '\0'; + return pos - buf; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get scan results, transform results from driver's format to WE's. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prData Pointer to iw_point structure, pData->length is the size of +* pcExtra buffer before used, and is updated after filling scan +* results. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 For success. +* \retval -ENOMEM If dynamic memory allocation fail. +* \retval -E2BIG Invalid length. +* +* \note Scan results is filled into pcExtra buffer, data size is updated in +* pData->length. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_scan ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN OUT struct iw_point *prData, + IN char *pcExtra + ) +{ + UINT_32 i = 0; + UINT_32 j = 0; + P_PARAM_BSSID_LIST_EX_T prList = NULL; + P_PARAM_BSSID_EX_T prBss = NULL; + P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; + struct iw_event iwEvent; /* local iw_event buffer */ + + /* write pointer of extra buffer */ + char *pcCur = NULL; + /* pointer to the end of last full entry in extra buffer */ + char *pcValidEntryEnd = NULL; + char *pcEnd = NULL; /* end of extra buffer */ + + UINT_32 u4AllocBufLen = 0; + + /* arrange rate information */ + UINT_32 u4HighestRate = 0; + char aucRatesBuf[64]; + UINT_32 u4BufIndex; + + /* return value */ + int ret = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prData, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Initialize local variables */ + pcCur = pcExtra; + pcValidEntryEnd = pcExtra; + pcEnd = pcExtra + prData->length; /* end of extra buffer */ + + /* Allocate another query buffer with the same size of extra buffer */ + u4AllocBufLen = prData->length; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(INIT, INFO, ("[wifi] no memory for scan list:%d\n", prData->length)); + ret = -ENOMEM; + goto error; + } + prList->u4NumberOfItems = 0; + + /* wait scan done */ + //printk ("wait for scan results\n"); + //wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, + prList, + u4AllocBufLen, + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + /* Buffer length is not large enough. */ + //printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); + +#if WIRELESS_EXT >= 17 + /* This feature is supported in WE-17 or above, limited by iwlist. + ** Return -E2BIG and iwlist will request again with a larger buffer. + */ + ret = -E2BIG; + /* Update length to give application a hint on result length */ + prData->length = (__u16)u4BufLen; + goto error; +#else + /* Realloc a larger query buffer here, but don't write too much to extra + ** buffer when filling it later. + */ + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + u4AllocBufLen = u4BufLen; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(INIT, INFO, ("[wifi] no memory for larger scan list :%ld\n", u4BufLen)); + ret = -ENOMEM; + goto error; + } + prList->NumberOfItems = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, + prList, + u4AllocBufLen, + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + DBGLOG(INIT, INFO, ("[wifi] larger buf:%d result:%ld\n", u4AllocBufLen, u4BufLen)); + ret = -E2BIG; + prData->length = (__u16)u4BufLen; + goto error; + } +#endif /* WIRELESS_EXT >= 17 */ + + } + + + if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) { + DBGLOG(INIT, INFO, ("[wifi] strange scan result count:%ld\n", + prList->u4NumberOfItems)); + goto error; + } + + /* Copy required data from pList to pcExtra */ + prBss = &prList->arBssid[0]; /* set to the first entry */ + for (i = 0; i < prList->u4NumberOfItems; ++i) { + /* BSSID */ + iwEvent.cmd = SIOCGIWAP; + iwEvent.len = IW_EV_ADDR_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress, ETH_ALEN); + memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN); + pcCur += IW_EV_ADDR_LEN; + + /* SSID */ + iwEvent.cmd = SIOCGIWESSID; + /* Modification to user space pointer(essid.pointer) is not needed. */ + iwEvent.u.essid.length = (__u16)prBss->rSsid.u4SsidLen; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length; + + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.essid.flags = 1; + iwEvent.u.essid.pointer = NULL; + +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, iwEvent.len); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length); + pcCur += iwEvent.len; + /* Frequency */ + iwEvent.cmd = SIOCGIWFREQ; + iwEvent.len = IW_EV_FREQ_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig; + iwEvent.u.freq.e = 3; /* (in KHz) */ + iwEvent.u.freq.i = 0; + memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN); + pcCur += IW_EV_FREQ_LEN; + + /* Operation Mode */ + iwEvent.cmd = SIOCGIWMODE; + iwEvent.len = IW_EV_UINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + if (prBss->eOpMode == NET_TYPE_IBSS) { + iwEvent.u.mode = IW_MODE_ADHOC; + } + else if (prBss->eOpMode == NET_TYPE_INFRA) { + iwEvent.u.mode = IW_MODE_INFRA; + } + else { + iwEvent.u.mode = IW_MODE_AUTO; + } + memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN); + pcCur += IW_EV_UINT_LEN; + + /* Quality */ + iwEvent.cmd = IWEVQUAL; + iwEvent.len = IW_EV_QUAL_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.qual.qual = 0; /* Quality not available now */ + /* -100 < Rssi < -10, normalized by adding 0x100 */ + iwEvent.u.qual.level = 0x100 + prBss->rRssi; + iwEvent.u.qual.noise = 0; /* Noise not available now */ + iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED \ + | IW_QUAL_NOISE_INVALID; + memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN); + pcCur += IW_EV_QUAL_LEN; + + /* Security Mode*/ + iwEvent.cmd = SIOCGIWENCODE; + iwEvent.len = IW_EV_POINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.pointer = NULL; + iwEvent.u.data.flags = 0; + iwEvent.u.data.length = 0; + if(!prBss->u4Privacy) { + iwEvent.u.data.flags |= IW_ENCODE_DISABLED; + } +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + pcCur += IW_EV_POINT_LEN; + + /* rearrange rate information */ + u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F; + if (curRate == 0) { + break; + } + + if (curRate > u4HighestRate) { + u4HighestRate = curRate; + } + + if (curRate == RATE_5_5M) { + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5"); + } + else { + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2); + } + #if DBG + if (u4BufIndex > sizeof(aucRatesBuf)) { + //printk("rate info too long\n"); + break; + } + #endif + } + /* Report Highest Rates */ + iwEvent.cmd = SIOCGIWRATE; + iwEvent.len = IW_EV_PARAM_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.bitrate.value = u4HighestRate * 500000; + iwEvent.u.bitrate.fixed = 0; + iwEvent.u.bitrate.disabled = 0; + iwEvent.u.bitrate.flags = 0; + memcpy(pcCur, &iwEvent, iwEvent.len); + pcCur += iwEvent.len; + + #if WIRELESS_EXT >= 15 /* IWEVCUSTOM is available in WE-15 or above */ + /* Report Residual Rates */ + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = u4BufIndex; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 0; + #if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); + #else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); + #endif + memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex); + pcCur += iwEvent.len; + #endif /* WIRELESS_EXT >= 15 */ + + + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } + +#if CFG_SUPPORT_WPS /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */ + if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#endif + + + /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */ + /* pBss->IEs starts from timestamp */ + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength -sizeof(PARAM_FIXED_IEs), + 0x30, + (PUINT_8 *)&prDesiredIE)) { + + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } + +#if CFG_SUPPORT_WAPI /* Android+ */ + if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength -sizeof(PARAM_FIXED_IEs), + (PUINT_8 *)&prDesiredIE)) { + +#if 0 + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; +#else + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 1; + + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, + sizeof(struct iw_point) - IW_EV_POINT_OFF); + + pcCur += (IW_EV_POINT_LEN); + + pcCur += sprintf(pcCur, "wapi_ie="); + + snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *)prDesiredIE, prDesiredIE->ucLength + 2); + + pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */; +#endif + } +#endif + /* Complete an entry. Update end of valid entry */ + pcValidEntryEnd = pcCur; + /* Extract next bss */ + prBss = (P_PARAM_BSSID_EX_T)((char *)prBss + prBss->u4Length); + } + + /* Update valid data length for caller function and upper layer + * applications. + */ + prData->length = (pcValidEntryEnd - pcExtra); + //printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); + + //kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + +error: + /* free local query buffer */ + if (prList) { + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + } + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set desired network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer of iw_point header. +* \param[in] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -E2BIG Essid string length is too big. +* \retval -EINVAL pcExtra is null pointer. +* \retval -EFAULT Driver fail to set new essid. +* +* \note If string lengh is ok, device will try connecting to the new network. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEssid, + IN char *pcExtra + ) +{ + PARAM_SSID_T rNewSsid; + UINT_32 cipher; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prEssid->length > IW_ESSID_MAX_SIZE) { + return -E2BIG; + } + + + /* set auth mode */ + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? + AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; + //printk(KERN_INFO "IW_AUTH_WPA_VERSION_DISABLED->Param_AuthMode%s\n", + // (eAuthMode == AUTH_MODE_OPEN) ? "Open" : "Shared"); + } + else { + /* set auth mode */ + switch(prGlueInfo->rWpaInfo.u4KeyMgmt) { + case IW_AUTH_KEY_MGMT_802_1X: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA : AUTH_MODE_WPA2; + //printk("IW_AUTH_KEY_MGMT_802_1X->AUTH_MODE_WPA%s\n", + // (eAuthMode == AUTH_MODE_WPA) ? "" : "2"); + break; + case IW_AUTH_KEY_MGMT_PSK: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA_PSK: AUTH_MODE_WPA2_PSK; + //printk("IW_AUTH_KEY_MGMT_PSK->AUTH_MODE_WPA%sPSK\n", + // (eAuthMode == AUTH_MODE_WPA_PSK) ? "" : "2"); + break; +#if CFG_SUPPORT_WAPI /* Android+ */ + case IW_AUTH_KEY_MGMT_WAPI_PSK: + break; + case IW_AUTH_KEY_MGMT_WAPI_CERT: + break; +#endif + +//#if defined (IW_AUTH_KEY_MGMT_WPA_NONE) +// case IW_AUTH_KEY_MGMT_WPA_NONE: +// eAuthMode = AUTH_MODE_WPA_NONE; +// //printk("IW_AUTH_KEY_MGMT_WPA_NONE->AUTH_MODE_WPA_NONE\n"); +// break; +//#endif +#if CFG_SUPPORT_802_11W + case IW_AUTH_KEY_MGMT_802_1X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + break; + case IW_AUTH_KEY_MGMT_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + break; +#endif + default: + //printk(KERN_INFO DRV_NAME"strange IW_AUTH_KEY_MGMT : %ld set auto switch\n", + // prGlueInfo->rWpaInfo.u4KeyMgmt); + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + /* set encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | + prGlueInfo->rWpaInfo.u4CipherPairwise; + if (cipher & IW_AUTH_CIPHER_CCMP) { + //printk("IW_AUTH_CIPHER_CCMP->ENUM_ENCRYPTION3_ENABLED\n"); + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } + else if (cipher & IW_AUTH_CIPHER_TKIP) { + //printk("IW_AUTH_CIPHER_TKIP->ENUM_ENCRYPTION2_ENABLED\n"); + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + } + else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + //printk("IW_AUTH_CIPHER_WEPx->ENUM_ENCRYPTION1_ENABLED\n"); + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } + else if (cipher & IW_AUTH_CIPHER_NONE){ + //printk("IW_AUTH_CIPHER_NONE->ENUM_ENCRYPTION_DISABLED\n"); + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + else { + //printk("unknown IW_AUTH_CIPHER->Param_EncryptionDisabled\n"); + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(eEncStatus), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + +#if WIRELESS_EXT < 21 + /* GeorgeKuo: a length error bug exists in (WE < 21) cases, kernel before + ** 2.6.19. Cut the trailing '\0'. + */ + rNewSsid.u4SsidLen = (prEssid->length) ? prEssid->length - 1 : 0; +#else + rNewSsid.u4SsidLen = prEssid->length; +#endif + kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen); + + /* + rNewSsid.aucSsid[rNewSsid.u4SsidLen] = '\0'; + printk("set ssid(%lu): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid); + */ + + if (kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID) &rNewSsid, + sizeof(PARAM_SSID_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen) != WLAN_STATUS_SUCCESS) { + //printk(KERN_WARNING "Fail to set ssid\n"); + return -EFAULT; + } + + + return 0; +} /* wext_set_essid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer to iw_point structure containing essid information. +* \param[out] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, network essid is stored in pcExtra. +*/ +/*----------------------------------------------------------------------------*/ +//static PARAM_SSID_T ssid; +static int +wext_get_essid ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEssid, + OUT char *pcExtra + ) +{ + //PARAM_SSID_T ssid; + + P_PARAM_SSID_T prSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + //if (!netif_carrier_ok(prNetDev)) { + // return -ENOTCONN; + //} + + prSsid = kalMemAlloc(sizeof(PARAM_SSID_T), VIR_MEM_TYPE); + + if(!prSsid) { + return -ENOMEM; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySsid, + prSsid, + sizeof(PARAM_SSID_T), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if ((rStatus == WLAN_STATUS_SUCCESS) && (prSsid->u4SsidLen <= MAX_SSID_LEN)) { + kalMemCopy(pcExtra, prSsid->aucSsid, prSsid->u4SsidLen); + prEssid->length = prSsid->u4SsidLen; + prEssid->flags = 1; + } + + kalMemFree(prSsid, VIR_MEM_TYPE, sizeof(PARAM_SSID_T)); + + return 0; +} /* wext_get_essid */ + + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set tx desired bit rate. Three cases here +* iwconfig wlan0 auto -> Set to origianl supported rate set. +* iwconfig wlan0 18M -> Imply "fixed" case, set to 18Mbps as desired rate. +* iwconfig wlan0 18M auto -> Set to auto rate lower and equal to 18Mbps +* +* \param[in] prNetDev Pointer to the net_device handler. +* \param[in] prIwReqInfo Pointer to the Request Info. +* \param[in] prRate Pointer to the Rate Parameter. +* \param[in] pcExtra Pointer to the extra buffer. +* +* \retval 0 Update desired rate. +* \retval -EINVAL Wrong parameter +*/ +/*----------------------------------------------------------------------------*/ +int +wext_set_rate ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN struct iw_param *prRate, + IN char *pcExtra + ) +{ + PARAM_RATES_EX aucSuppRate = {0}; + PARAM_RATES_EX aucNewRate = {0}; + UINT_32 u4NewRateLen = 0; + UINT_32 i; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + printk("value = %d, fixed = %d, disable = %d, flags = %d\n", + prRate->value, prRate->fixed, prRate->disabled, prRate->flags); + */ + + rStatus = wlanQueryInformation( + prGlueInfo->prAdapter, + wlanoidQuerySupportedRates, + &aucSuppRate, + sizeof(aucSuppRate), + &u4BufLen); + + /* Case: AUTO */ + if (prRate->value < 0) { + if (prRate->fixed == 0) { + /* iwconfig wlan0 rate auto */ + + /* set full supported rate to device */ + /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */ + rStatus = wlanSetInformation( + prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, + sizeof(aucSuppRate), + &u4BufLen); + return 0; + } + else { + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + } + + + aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) { + break; + } + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) { + break; + } + + if (aucSuppRate[i] < aucNewRate[0]) { + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + } + + rStatus = wlanSetInformation( + prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucNewRate, + sizeof(aucNewRate), + &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current tx bit rate. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRate Pointer to iw_param structure to store current tx rate. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, current tx rate is stored in pRate. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prRate, + IN char *pcExtra + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) { + return -ENOTCONN; + } + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, + &u4Rate, + sizeof(u4Rate), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + + prRate->value = u4Rate * 100; /* u4Rate is in unit of 100bps */ + prRate->fixed = 0; + + return 0; +} /* wext_get_rate */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set RTS/CTS theshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prRts Pointer to iw_param structure containing rts threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EINVAL Given value is out of range. +* +* \note If given value is valid, device will follow the new setting. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_rts ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_param *prRts, + IN char *pcExtra + ) +{ + PARAM_RTS_THRESHOLD u4RtsThresh; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prRts->disabled == 1) { + u4RtsThresh = 2347; + } + else if (prRts->value < 0 || prRts->value > 2347) { + return -EINVAL; + } + else { + u4RtsThresh = (PARAM_RTS_THRESHOLD)prRts->value; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRtsThreshold, + &u4RtsThresh, + sizeof(u4RtsThresh), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + prRts->value = (typeof(prRts->value ))u4RtsThresh; + prRts->disabled = (prRts->value > 2347) ? 1 : 0; + prRts->fixed = 1; + + return 0; +} /* wext_set_rts */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get RTS/CTS theshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRts Pointer to iw_param structure containing rts threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note RTS threshold is stored in pRts. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rts ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prRts, + IN char *pcExtra + ) +{ + PARAM_RTS_THRESHOLD u4RtsThresh; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRtsThreshold, + &u4RtsThresh, + sizeof(u4RtsThresh), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + prRts->value = (typeof(prRts->value ))u4RtsThresh; + prRts->disabled = (prRts->value > 2347 || prRts->value < 0) ? 1 : 0; + prRts->fixed = 1; + + return 0; +} /* wext_get_rts */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get fragmentation threshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prFrag Pointer to iw_param structure containing frag threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note RTS threshold is stored in pFrag. Fragmentation is disabled. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_frag ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prFrag, + IN char *pcExtra + ) +{ + ASSERT(prFrag); + + prFrag->value = 2346; + prFrag->fixed = 1; + prFrag->disabled = 1; + return 0; +} /* wext_get_frag */ + +#if 1 +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set TX power, or enable/disable the radio. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prTxPow Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Tx power is stored in pTxPow. iwconfig wlan0 txpow on/off are used +* to enable/disable the radio. +*/ +/*----------------------------------------------------------------------------*/ + +static int +wext_set_txpow ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_param *prTxPow, + IN char *pcExtra + ) +{ + int ret = 0; + //PARAM_DEVICE_POWER_STATE ePowerState; + ENUM_ACPI_STATE_T ePowerState; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if(prTxPow->disabled){ + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDisassociate, + NULL, + 0, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("######set disassoc failed\n")); + } else { + DBGLOG(INIT, INFO, ("######set assoc ok\n")); + } + + /* <2> mark to power state flag*/ + ePowerState = ACPI_STATE_D0; + DBGLOG(INIT, INFO, ("set to acpi d3(0)\n")); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + + } + else { + ePowerState = ACPI_STATE_D0; + DBGLOG(INIT, INFO, ("set to acpi d0\n")); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + } + + prGlueInfo->ePowerState = ePowerState; + + return ret; +} /* wext_set_txpow */ + + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get TX power. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prTxPow Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Tx power is stored in pTxPow. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_txpow ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prTxPow, + IN char *pcExtra + ) +{ + //PARAM_DEVICE_POWER_STATE ePowerState; + + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not + * current state. Use GLUE_INFO_T to store state. + */ + //ePowerState = prGlueInfo->ePowerState; + + /* TxPow parameters: Fixed at relative 100% */ +#if WIRELESS_EXT < 17 + prTxPow->flags = 0x0002; /* IW_TXPOW_RELATIVE */ +#else + prTxPow->flags = IW_TXPOW_RELATIVE; +#endif + prTxPow->value = 100; + prTxPow->fixed = 1; + //prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE; + prTxPow->disabled = TRUE; + + return 0; +} /* wext_get_txpow */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Buffer to store key content. +* +* \retval 0 Success. +* +* \note Securiry information is stored in pEnc except key content. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_encode ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_point *prEnc, + IN char *pcExtra + ) +{ +#if 1 + //ENUM_ENCRYPTION_STATUS_T eEncMode; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (FALSE == GLUE_CHK_PR2(prNetDev, prEnc)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEncryptionStatus, + &eEncMode, + sizeof(eEncMode), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + + + switch(eEncMode) { + case ENUM_WEP_DISABLED: + prEnc->flags = IW_ENCODE_DISABLED; + break; + case ENUM_WEP_ENABLED: + prEnc->flags = IW_ENCODE_ENABLED; + break; + case ENUM_WEP_KEY_ABSENT: + prEnc->flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + break; + default: + prEnc->flags = IW_ENCODE_ENABLED; + break; + } + + /* Cipher, Key Content, Key ID can't be queried */ + prEnc->flags |= IW_ENCODE_NOKEY; +#endif + return 0; +} /* wext_get_encode */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 wepBuf[48]; + +static int +wext_set_encode ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEnc, + IN char *pcExtra + ) +{ +#if 1 + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + //UINT_8 wepBuf[48]; + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* reset to default mode */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + /* iwconfig wlan0 key off */ + if ( (prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED ) { + eAuthMode = AUTH_MODE_OPEN; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(eEncStatus), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + return 0; + } + + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) -1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prEnc->length; + prWepKey->u4KeyLength = prEnc->length; + kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, + prWepKey->u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus)); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | + IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus); + return -EFAULT; + } + + return 0; + } +#endif + return -EOPNOTSUPP; +} /* wext_set_encode */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note New Power Management Mode is set to driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_power ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_param *prPower, + IN char *pcExtra + ) +{ +#if 1 + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + //printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", + // prPower->value, prPower->disabled, prPower->flags); + + if(prPower->disabled){ + ePowerMode = Param_PowerModeCAM; + } + else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + else { + DBGLOG(INIT, INFO, ("%s(): unsupported power management mode value = %d.\n", + __FUNCTION__, + prPower->value)); + + return -EINVAL; + } + } + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); + return -EFAULT; + } + +#endif + return 0; +} /* wext_set_power */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Power management mode is stored in pTxPow->value. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_power ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prPower, + IN char *pcExtra + ) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if 0 +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + TRUE, + TRUE, + &u4BufLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + &u4BufLen); +#endif +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, + sizeof(ePowerMode), + &u4BufLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + return -EFAULT; + } + + prPower->value = 0; + prPower->disabled = 1; + + if (Param_PowerModeCAM == ePowerMode) { + prPower->value = 0; + prPower->disabled = 1; + } + else if (Param_PowerModeMAX_PSP == ePowerMode ) { + prPower->value = 1; + prPower->disabled = 0; + } + else if (Param_PowerModeFast_PSP == ePowerMode ) { + prPower->value = 2; + prPower->disabled = 0; + } + + prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; +#if WIRELESS_EXT < 21 + prPower->value *= 1000000; +#endif + + //printk(KERN_INFO "wext_get_power value(%d) disabled(%d) flag(0x%x)\n", + // prPower->value, prPower->disabled, prPower->flags); + + return 0; +} /* wext_get_power */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set authentication parameters. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] rpAuth Pointer to iw_param structure containing authentication information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_auth ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_param *prAuth, + IN char *pcExtra + ) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prAuth); + if (FALSE == GLUE_CHK_PR2(prNetDev, prAuth)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Save information to glue info and process later when ssid is set. */ + switch(prAuth->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prGlueInfo->prAdapter)){ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + } + else { + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; + } +#else + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; +#endif + break; + + case IW_AUTH_CIPHER_PAIRWISE: + prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value; + break; + + case IW_AUTH_CIPHER_GROUP: + prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value; + break; + + case IW_AUTH_KEY_MGMT: + prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value; +#if CFG_SUPPORT_WAPI + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK || + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT) { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, + sizeof(UINT_32), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value)); + } +#endif + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS) + prGlueInfo->fgWpsActive = TRUE; + else + prGlueInfo->fgWpsActive = FALSE; + break; + + case IW_AUTH_80211_AUTH_ALG: + prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value; + break; + + case IW_AUTH_PRIVACY_INVOKED: + prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value; + break; +#if CFG_SUPPORT_802_11W + case IW_AUTH_MFP: + //printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); + prGlueInfo->rWpaInfo.u4Mfp = prAuth->value; + break; +#endif +#if CFG_SUPPORT_WAPI + case IW_AUTH_WAPI_ENABLED: + { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, + sizeof(UINT_32), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + } + DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value)); + break; +#endif + default: + /* + printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags); + */ + break; + } + return 0; +} /* wext_set_auth */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_WAPI + UINT_8 keyStructBuf[320]; /* add/remove key shared buffer */ +#else + UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +static int +wext_set_encode_ext ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEnc, + IN char *pcExtra + ) +{ + P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; + P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; + + + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *) pcExtra; + + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + //ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; + +#if CFG_SUPPORT_WAPI + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; +#endif + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + +#if CFG_SUPPORT_WAPI + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + if (prEnc->flags & IW_ENCODE_DISABLED) { + //printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n"); + return 0; + } + /* KeyID */ + prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); + prWpiKey->ucKeyID --; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + //printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + //printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); + return -EINVAL; + } + + //printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } + else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } + + /* PN */ + memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE * 2); + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, + sizeof(PARAM_WPI_KEY_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); + } + + } + else +#endif + { + + if ( (prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + /* + printk("IW_ENCODE_DISABLED: ID:%d, Addr:[" MACSTR "]\n", + prRemoveKey->KeyIndex, MAC2STR(prRemoveKey->BSSID)); + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + prRemoveKey, + prRemoveKey->u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("remove key error:%lx\n", rStatus)); + } + return 0; + } + + //return 0; + //printk ("alg %x\n", prIWEncExt->alg); + + switch (prIWEncExt->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) -1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prIWEncExt->key_len; + prWepKey->u4KeyLength = prIWEncExt->key_len; + //kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); + kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, + prWepKey->u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus)); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | + IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetAuthMode fail 0x%lx\n", rStatus)); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus)); + return -EFAULT; + } + + } else { + DBGLOG(INIT, INFO, ("key length %x\n", prIWEncExt->key_len)); + DBGLOG(INIT, INFO, ("key error\n")); + } + + break; + case IW_ENCODE_ALG_TKIP: + case IW_ENCODE_ALG_CCMP: +#if CFG_SUPPORT_802_11W + case IW_ENCODE_ALG_AES_CMAC: +#endif + { + + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) -1: 0; +#if CFG_SUPPORT_802_11W + if (prKey->u4KeyIndex > 5) +#else + if (prKey->u4KeyIndex > 3) +#endif + { + DBGLOG(INIT, INFO, ("key index error:0x%lx\n", prKey->u4KeyIndex)); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31)*/ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prKey->u4KeyIndex |= 0x1UL << 31; + } + + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + } + else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + + } + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + /* switch tx/rx MIC key for sta */ + if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) { + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16); + memcpy(((PUINT_8)prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24, 8); + memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8); + } + else { + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((UINT_32)&(((P_PARAM_KEY_T)0)->aucKeyMaterial)) + prKey->u4KeyLength; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + prKey, + prKey->u4Length, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("add key error:%lx\n", rStatus)); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set country code +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] pu4Mode Pointer to new operation mode. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If new mode is not supported. +* +* \note Device will run in new operation mode if it is valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_country ( + IN struct net_device *prNetDev, + IN struct iwreq *iwr + ) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 aucCountry[2]; + + ASSERT(prNetDev); + + /* iwr->u.data.pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (FALSE == GLUE_CHK_PR2(prNetDev, iwr) || + !iwr->u.data.pointer || iwr->u.data.length < 10) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + aucCountry[0] = *((PUINT_8)iwr->u.data.pointer + 8); + aucCountry[1] = *((PUINT_8)iwr->u.data.pointer + 9); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[0], + 2, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl() (Linux Wireless Extensions) routines +* +* \param[in] prDev Net device requested. +* \param[in] ifr The ifreq structure for seeting the wireless extension. +* \param[in] i4Cmd The wireless extension ioctl command. +* +* \retval zero On success. +* \retval -EOPNOTSUPP If the cmd is not supported. +* \retval -EFAULT If copy_to_user goes wrong. +* \retval -EINVAL If any value's out of range. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +wext_support_ioctl ( + IN struct net_device *prDev, + IN struct ifreq *prIfReq, + IN int i4Cmd + ) +{ + /* prIfReq is verified in the caller function wlanDoIOCTL() */ + struct iwreq *iwr = (struct iwreq*)prIfReq; + struct iw_request_info rIwReqInfo; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + + /* prDev is verified in the caller function wlanDoIOCTL() */ + + printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd); + + /* Prepare the call */ + rIwReqInfo.cmd = (__u16)i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case SIOCGIWNAME: /* 0x8B01, get wireless protocol name */ + ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + //ret = 0; + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size shoule be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = - ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, + prExtraBuf, + iwr->u.data.length)) { + ret = -EFAULT; + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); + prExtraBuf = NULL; + } + else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, Country */ + ret = wext_set_country(prDev, iwr); + break; + + /* case SIOCGIWPRIV: 0x8B0D, handled in wlan_do_ioctl() */ + /* caes SIOCSIWSTATS: 0x8B0E, unused */ + /* case SIOCGIWSTATS: + get statistics, intercepted by wireless_process_ioctl() in wireless.c, + redirected to dev_iwstats(), dev->get_wireless_stats(). + */ + /* case SIOCSIWSPY: 0x8B10, unsupported */ + /* case SIOCGIWSPY: 0x8B11, unsupported*/ + /* case SIOCSIWTHRSPY: 0x8B12, unsupported */ + /* case SIOCGIWTHRSPY: 0x8B13, unsupported*/ + + case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */ + if (iwr->u.ap_addr.sa_data[0] == 0 && + iwr->u.ap_addr.sa_data[1] == 0 && + iwr->u.ap_addr.sa_data[2] == 0 && + iwr->u.ap_addr.sa_data[3] == 0 && + iwr->u.ap_addr.sa_data[4] == 0 && + iwr->u.ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + ** wpa_driver_wext_deinit(), do nothing here or disassoc again? + */ + ret = 0; + break; + } + else { + ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + } + break; + + case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */ + ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + break; + + case SIOCSIWMLME: /* 0x8B16, request MLME operation */ + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_mlme)) { + DBGLOG(INIT, INFO, ("MLME buffer strange:%d\n", iwr->u.data.length)); + ret = -EINVAL; + break; + } + + if (!iwr->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = - ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) { + ret = -EFAULT; + } + else { + ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + /* case SIOCGIWAPLIST: 0x8B17, deprecated */ + case SIOCSIWSCAN: /* 0x8B18, scan request */ + if (iwr->u.data.pointer == NULL) { + ret = wext_set_scan(prDev, NULL, NULL, NULL); + } +#if WIRELESS_EXT > 17 + else if (iwr->u.data.length == sizeof(struct iw_scan_req)) { + prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, ((struct iw_scan_req *) (iwr->u.data.pointer))->essid, + ((struct iw_scan_req *) (iwr->u.data.pointer))->essid_len)) { + ret = -EFAULT; + } else { + ret = wext_set_scan(prDev, NULL, (union iwreq_data *) &(iwr->u.data), prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, MAX_SSID_LEN); + prExtraBuf = NULL; + } +#endif + else { + ret = -EINVAL; + } + break; +#if 1 + case SIOCGIWSCAN: /* 0x8B19, get scan results */ + if (!iwr->u.data.pointer|| !iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + u4ExtraSize = iwr->u.data.length; + /* allocate the same size of kernel buffer to store scan results. */ + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = - ENOMEM; + break; + } + + /* iwr->u.data.length may be updated by wext_get_scan() */ + ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf); + if (ret != 0) { + if (ret == -E2BIG) { + DBGLOG(INIT, INFO, ("[wifi] wext_get_scan -E2BIG\n")); + } + } + else { + /* check updated length is valid */ + ASSERT(iwr->u.data.length <= u4ExtraSize); + if (iwr->u.data.length > u4ExtraSize) { + DBGLOG(INIT, INFO, ("Updated result length is larger than allocated (%d > %ld)\n", + iwr->u.data.length, u4ExtraSize)); + iwr->u.data.length = u4ExtraSize; + } + + if (copy_to_user(iwr->u.data.pointer, + prExtraBuf, + iwr->u.data.length)) { + ret = -EFAULT; + } + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + break; + +#endif + +#if 1 + case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */ + if (iwr->u.essid.length > IW_ESSID_MAX_SIZE) { + ret = -E2BIG; + break; + } + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 4, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = - ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + iwr->u.essid.pointer, + iwr->u.essid.length)) { + ret = -EFAULT; + } + else { + /* Add trailing '\0' for printk */ + //prExtraBuf[iwr->u.essid.length] = 0; + //printk(KERN_INFO "wext_set_essid: %s (%d)\n", prExtraBuf, iwr->u.essid.length); + ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); + //printk ("set essid %d\n", ret); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4); + prExtraBuf = NULL; + break; + +#endif + + case SIOCGIWESSID: /* 0x8B1B, get SSID */ + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (iwr->u.essid.length < IW_ESSID_MAX_SIZE) { + DBGLOG(INIT, INFO, ("[wifi] iwr->u.essid.length:%d too small\n", + iwr->u.essid.length)); + ret = -E2BIG; /* let caller try larger buffer */ + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* iwr->u.essid.length is updated by wext_get_essid() */ + + ret = wext_get_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); + if (ret == 0) { + if (copy_to_user(iwr->u.essid.pointer, prExtraBuf, iwr->u.essid.length)) { + ret = -EFAULT; + } + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE); + prExtraBuf = NULL; + + break; + + /* case SIOCSIWNICKN: 0x8B1C, not supported */ + /* case SIOCGIWNICKN: 0x8B1D, not supported */ + + case SIOCSIWRATE: /* 0x8B20, set default bit rate (bps) */ + //ret = wext_set_rate(prDev, &rIwReqInfo, &iwr->u.bitrate, NULL); + break; + + case SIOCGIWRATE: /* 0x8B21, get current bit rate (bps) */ + ret = wext_get_rate(prDev, NULL, &iwr->u.bitrate, NULL); + break; + + case SIOCSIWRTS: /* 0x8B22, set rts/cts threshold */ + ret = wext_set_rts(prDev, NULL, &iwr->u.rts, NULL); + break; + + case SIOCGIWRTS: /* 0x8B23, get rts/cts threshold */ + ret = wext_get_rts(prDev, NULL, &iwr->u.rts, NULL); + break; + + /* case SIOCSIWFRAG: 0x8B24, unsupported */ + case SIOCGIWFRAG: /* 0x8B25, get frag threshold */ + ret = wext_get_frag(prDev, NULL, &iwr->u.frag, NULL); + break; + + case SIOCSIWTXPOW: /* 0x8B26, set relative tx power (in %) */ + ret = wext_set_txpow(prDev, NULL, &iwr->u.txpower, NULL); + break; + + case SIOCGIWTXPOW: /* 0x8B27, get relative tx power (in %) */ + ret = wext_get_txpow(prDev, NULL, &iwr->u.txpower, NULL); + break; + + /* case SIOCSIWRETRY: 0x8B28, unsupported */ + /* case SIOCGIWRETRY: 0x8B29, unsupported */ + +#if 1 + case SIOCSIWENCODE: /* 0x8B2A, set encoding token & mode */ + /* Only DISABLED case has NULL pointer and length == 0 */ + if (iwr->u.encoding.pointer) { + if (iwr->u.encoding.length > 16) { + ret = -E2BIG; + break; + } + + u4ExtraSize = iwr->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + iwr->u.encoding.pointer, + iwr->u.encoding.length)) { + ret = -EFAULT; + } + } + else if (iwr->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) { + ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf); + } + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + break; + + case SIOCGIWENCODE: /* 0x8B2B, get encoding token & mode */ + /* check pointer */ + ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL); + break; + + case SIOCSIWPOWER: /* 0x8B2C, set power management */ + ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL); + break; + + case SIOCGIWPOWER: /* 0x8B2D, get power management */ + ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL); + break; + +#if WIRELESS_EXT > 17 + case SIOCSIWGENIE: /* 0x8B30, set gen ie */ + if (iwr->u.data.pointer) { + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) { + /* Fixed length structure */ +#if CFG_SUPPORT_WAPI + if (iwr->u.data.length > 42 /* The max wapi ie buffer */) { + ret = -EINVAL; + break; + } +#endif + u4ExtraSize = iwr->u.data.length; + if (u4ExtraSize) { + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, + iwr->u.data.pointer, + iwr->u.data.length)) { + ret = -EFAULT; + } + else { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + prExtraBuf, + u4ExtraSize, + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", rStatus); +#endif +#if CFG_SUPPORT_WPS2 + PUINT_8 prDesiredIE = NULL; + if (wextSrchDesiredWPSIE(prExtraBuf, + u4ExtraSize, + 0xDD, + (PUINT_8 *)&prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWSCAssocInfo, + prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + //printk(KERN_INFO "[WSC] set WSC assoc info error:%lx\n", rStatus); + } + } +#endif +#if CFG_SUPPORT_WAPI + } +#endif + } + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + } + } + break; + + case SIOCGIWGENIE: /* 0x8B31, get gen ie, unused */ + break; + +#endif + + case SIOCSIWAUTH: /* 0x8B32, set auth mode params */ + ret = wext_set_auth(prDev, NULL, &iwr->u.param, NULL); + break; + + /* case SIOCGIWAUTH: 0x8B33, unused? */ + case SIOCSIWENCODEEXT: /* 0x8B34, set extended encoding token & mode */ + if (iwr->u.encoding.pointer) { + u4ExtraSize = iwr->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + iwr->u.encoding.pointer, + iwr->u.encoding.length)) { + ret = -EFAULT; + } + } + else if (iwr->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) { + ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf); + } + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + break; + + /* case SIOCGIWENCODEEXT: 0x8B35, unused? */ + + case SIOCSIWPMKSA: /* 0x8B36, pmksa cache operation */ + #if 1 + if (iwr->u.data.pointer) { + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_pmksa)) { + ret = -EINVAL; + break; + } + + u4ExtraSize = sizeof(struct iw_pmksa); + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, + iwr->u.data.pointer, + sizeof(struct iw_pmksa))) { + ret = -EFAULT; + } + else { + switch(((struct iw_pmksa *)prExtraBuf)->cmd) { + case IW_PMKSA_ADD: + /* + printk(KERN_INFO "IW_PMKSA_ADD [" MACSTR "]\n", + MAC2STR(((struct iw_pmksa *)pExtraBuf)->bssid.sa_data)); + */ + { + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_ADD\n")); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, + ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, + 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, + ((struct iw_pmksa *)prExtraBuf)->pmkid, + IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("add pmkid error:%lx\n", rStatus)); + } + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + } + break; + case IW_PMKSA_REMOVE: + /* + printk(KERN_INFO "IW_PMKSA_REMOVE [" MACSTR "]\n", + MAC2STR(((struct iw_pmksa *)buf)->bssid.sa_data)); + */ + break; + case IW_PMKSA_FLUSH: + /* + printk(KERN_INFO "IW_PMKSA_FLUSH\n"); + */ + { + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_FLUSH\n")); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, ("flush pmkid error:%lx\n", rStatus)); + } + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + } + break; + default: + DBGLOG(INIT, INFO, ("UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)prExtraBuf)->cmd)); + ret = -EFAULT; + break; + } + } + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + } + else if (iwr->u.data.length != 0) { + ret = -EINVAL; + break; + } + #endif + break; + +#endif + + default: + /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */ + ret = -EOPNOTSUPP; + break; + } + + //printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret); + + return ret; +} /* wext_support_ioctl */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To send an event (RAW socket pacekt) to user process actively. +* +* \param[in] prGlueInfo Glue layer info. +* \param[in] u4cmd Whcih event command we want to indicate to user process. +* \param[in] pData Data buffer to be indicated. +* \param[in] dataLen Available data size in pData. +* +* \return (none) +* +* \note Event is indicated to upper layer if cmd is supported and data is valid. +* Using of kernel symbol wireless_send_event(), which is defined in +* after WE-14 (2.4.20). +*/ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event ( + IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, + IN unsigned char *pucData, + IN unsigned int u4dataLen + ) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; +#if WIRELESS_EXT >= 15 + unsigned char *pucDesiredIE = NULL; + unsigned char aucExtraInfoBuf[200]; +#endif +#if WIRELESS_EXT < 18 + int i; +#endif + + memset(&wrqu, 0, sizeof(wrqu)); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) { + memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN); + } + else { + memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN); + } + break; + + case IWEVASSOCREQIE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) { + /* RSN IE found */ + } +#if 0 + else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPS IE found */ + } +#endif + else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + } +#if CFG_SUPPORT_WAPI /* Android+ */ + else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) { + //printk("wextSrchDesiredWAPIIE!!\n"); + /* WAPI IE found */ + } +#endif + else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } + + #if WIRELESS_EXT < 18 + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs="); + /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */ + /* translate binary string to hex string, requirement of IWEVCUSTOM */ + for (i = 0; i < pucDesiredIE[1] + 2 ; ++i) { + pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]); + } + pucExtraInfo = aucExtraInfoBuf; + wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2; + #else + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + #endif +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVMICHAELMICFAILURE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + if (pucData) { + P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T)pucData; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, + "MLME-MICHAELMICFAILURE.indication "); + pucExtraInfo += sprintf(pucExtraInfo, + "%s", + (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + wrqu.data.length = pucExtraInfo - aucExtraInfoBuf; + pucExtraInfo = aucExtraInfoBuf; + } +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVPMKIDCAND: + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 && + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { + + /* only used in WPA2 */ +#if WIRELESS_EXT >= 18 + P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T)pucData; + + struct iw_pmkid_cand rPmkidCand; + pucExtraInfo = aucExtraInfoBuf; + + rPmkidCand.flags = prPmkidCand->u4Flags; + rPmkidCand.index = 0; + kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6); + + kalMemCopy(pucExtraInfo, (PUINT_8)&rPmkidCand, sizeof(struct iw_pmkid_cand)); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + + /* pmkid canadidate list is supported after WE-18 */ + /* indicate struct iw_pmkid_cand */ +#else + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */ + goto skip_indicate_event; +#endif + } + else { + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */ + goto skip_indicate_event; + } + break; + + case IWEVCUSTOM: + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T)); + wrqu.data.length = sizeof(PTA_IPC_T); + break; + + default: + /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */ + goto skip_indicate_event; + } + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; +} /* wext_indicate_wext_event */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] pDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +* +*/ +/*----------------------------------------------------------------------------*/ +struct iw_statistics * +wext_get_wireless_stats ( + struct net_device *prDev + ) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + goto stat_out; + } + + pStats = (struct iw_statistics *) (&(prGlueInfo->rIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, + &i4Rssi, + sizeof(i4Rssi), + TRUE, + TRUE, + TRUE, + FALSE, + &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To report the private supported IOCTLs table to user space. +* +* \param[in] prNetDev Net device requested. +* \param[out] prIfReq Pointer to ifreq structure, content is copied back to +* user space buffer in gl_iwpriv_table. +* +* \retval 0 For success. +* \retval -E2BIG For user's buffer size is too small. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +wext_get_priv ( + IN struct net_device *prNetDev, + IN struct ifreq *prIfReq + ) +{ + /* prIfReq is verified in the caller function wlanDoIOCTL() */ + struct iwreq *prIwReq = (struct iwreq *)prIfReq; + struct iw_point *prData= (struct iw_point *)&prIwReq->u.data; + UINT_16 u2BufferSize = 0; + + u2BufferSize = prData->length; + + /* update our private table size */ + prData->length = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args); + + if (u2BufferSize < prData->length) { + return -E2BIG; + } + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) { + return -EFAULT; + } + } + + return 0; +} /* wext_get_priv */ + +#endif /* WIRELESS_EXT */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c new file mode 100755 index 000000000000..aafe5696310a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c @@ -0,0 +1,2238 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext_priv.c#4 $ +*/ + +/*! \file gl_wext_priv.c + \brief This file includes private ioctl support. +*/ + + + +/* +** $Log: gl_wext_priv.c $ + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 20 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function[WCXRP00001202] [MT6628 Wi-Fi][FW] Adding the New PN init code + * use return to avoid the ioctl return not supported + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 11 02 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Fixed typo. + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 26 2011 wh.su + * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux + * adding the SW cmd ioctl support, use set/get structure ioctl. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Adjust OID order. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Support set PS profile and set WMM-PS related iwpriv. + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 24 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * correct typo for NVRAM access. + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable OID_CUSTOM_MTK_WIFI_TEST for RFTest & META tool + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix private ioctl for rftest + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support +** \main\maintrunk.MT5921\32 2009-10-08 10:33:25 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers. +** \main\maintrunk.MT5921\31 2009-09-29 16:46:21 GMT mtk01090 +** Remove unused functions +** \main\maintrunk.MT5921\30 2009-09-29 14:46:47 GMT mtk01090 +** Fix compile warning +** \main\maintrunk.MT5921\29 2009-09-29 14:28:48 GMT mtk01090 +** Fix compile warning +** \main\maintrunk.MT5921\28 2009-09-28 22:21:38 GMT mtk01090 +** Refine lines to supress compile warning +** \main\maintrunk.MT5921\27 2009-09-28 20:19:14 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\26 2009-08-18 22:56:53 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\25 2009-05-07 22:26:15 GMT mtk01089 +** Add mandatory and private IO control for Linux BWCS +** \main\maintrunk.MT5921\24 2009-04-29 10:07:05 GMT mtk01088 +** fixed the compiling error at linux +** \main\maintrunk.MT5921\23 2009-04-24 09:09:45 GMT mtk01088 +** mark the code not used at linux supplicant v0.6.7 +** \main\maintrunk.MT5921\22 2008-11-24 21:03:51 GMT mtk01425 +** 1. Add PTA_ENABLED flag +** \main\maintrunk.MT5921\21 2008-08-29 14:55:59 GMT mtk01088 +** adjust the code for meet the coding style, and add assert check +** \main\maintrunk.MT5921\20 2008-07-16 15:23:20 GMT mtk01104 +** Support GPIO2 mode +** \main\maintrunk.MT5921\19 2008-07-15 17:43:11 GMT mtk01084 +** modify variable name +** \main\maintrunk.MT5921\18 2008-07-14 14:37:58 GMT mtk01104 +** Add exception handle about length in function priv_set_struct() +** \main\maintrunk.MT5921\17 2008-07-14 13:55:32 GMT mtk01104 +** Support PRIV_CMD_BT_COEXIST +** \main\maintrunk.MT5921\16 2008-07-09 00:20:15 GMT mtk01461 +** Add priv oid to support WMM_PS_TEST +** \main\maintrunk.MT5921\15 2008-06-02 11:15:22 GMT mtk01461 +** Update after wlanoidSetPowerMode changed +** \main\maintrunk.MT5921\14 2008-05-30 19:31:07 GMT mtk01461 +** Add IOCTL for Power Mode +** \main\maintrunk.MT5921\13 2008-05-30 18:57:15 GMT mtk01461 +** Not use wlanoidSetCSUMOffloadForLinux() +** \main\maintrunk.MT5921\12 2008-05-30 15:13:18 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\11 2008-05-29 14:16:31 GMT mtk01084 +** rename for wlanoidSetBeaconIntervalForLinux +** \main\maintrunk.MT5921\10 2008-04-17 23:06:37 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\9 2008-03-31 21:00:55 GMT mtk01461 +** Add priv IOCTL for VOIP setting +** \main\maintrunk.MT5921\8 2008-03-31 13:49:43 GMT mtk01461 +** Add priv ioctl to turn on / off roaming +** \main\maintrunk.MT5921\7 2008-03-26 15:35:14 GMT mtk01461 +** Add CSUM offload priv ioctl for Linux +** \main\maintrunk.MT5921\6 2008-03-11 14:50:59 GMT mtk01461 +** Unify priv ioctl +** \main\maintrunk.MT5921\5 2007-11-06 19:32:30 GMT mtk01088 +** add WPS code +** \main\maintrunk.MT5921\4 2007-10-30 12:01:39 GMT MTK01425 +** 1. Update wlanQueryInformation and wlanSetInformation +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "gl_wext_priv.h" +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / sizeof(WLAN_REQ_ENTRY)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int +priv_get_ndis ( + IN struct net_device *prNetDev, + IN NDIS_TRANSPORT_STRUCT* prNdisReq, + OUT PUINT_32 pu4OutputLen + ); + +static int +priv_set_ndis ( + IN struct net_device *prNetDev, + IN NDIS_TRANSPORT_STRUCT* prNdisReq, + OUT PUINT_32 pu4OutputLen + ); + +#if 0 /* CFG_SUPPORT_WPS */ +static int +priv_set_appie ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + OUT char *pcExtra + ); + +static int +priv_set_filter ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + OUT char *pcExtra + ); +#endif /* CFG_SUPPORT_WPS */ + +static BOOLEAN +reqSearchSupportedOidEntry ( + IN UINT_32 rOid, + OUT P_WLAN_REQ_ENTRY *ppWlanReqEntry + ); + +#if 0 +static WLAN_STATUS +reqExtQueryConfiguration ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +static WLAN_STATUS +reqExtSetConfiguration ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); +#endif + +static WLAN_STATUS +reqExtSetAcpiDevicePowerState ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_8 aucOidBuf[4096] = {0}; + +/* OID processing table */ +/* Order is important here because the OIDs should be in order of + increasing value for binary searching. */ +static WLAN_REQ_ENTRY arWlanOidReqTable[] = { + /* + {(NDIS_OID)rOid, + (PUINT_8)pucOidName, + fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, + pfOidQueryHandler, + pfOidSetHandler} + */ + /* General Operational Characteristics */ + + /* Ethernet Operational Characteristics */ + {OID_802_3_CURRENT_ADDRESS, + DISP_STRING("OID_802_3_CURRENT_ADDRESS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 6, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentAddr, + NULL}, + + /* OID_802_3_MULTICAST_LIST */ + /* OID_802_3_MAXIMUM_LIST_SIZE */ + /* Ethernet Statistics */ + + /* NDIS 802.11 Wireless LAN OIDs */ + {OID_802_11_SUPPORTED_RATES, + DISP_STRING("OID_802_11_SUPPORTED_RATES"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_RATES_EX), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySupportedRates, + NULL}, + /* + {OID_802_11_CONFIGURATION, + DISP_STRING("OID_802_11_CONFIGURATION"), + TRUE, TRUE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_802_11_CONFIG_T), + (PFN_OID_HANDLER_FUNC_REQ)reqExtQueryConfiguration, + (PFN_OID_HANDLER_FUNC_REQ)reqExtSetConfiguration}, + */ + {OID_PNP_SET_POWER, + DISP_STRING("OID_PNP_SET_POWER"), + TRUE, FALSE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_DEVICE_POWER_STATE), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)reqExtSetAcpiDevicePowerState}, + + /* Custom OIDs */ + {OID_CUSTOM_OID_INTERFACE_VERSION, + DISP_STRING("OID_CUSTOM_OID_INTERFACE_VERSION"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryOidInterfaceVersion, + NULL}, + + /* +#if PTA_ENABLED + {OID_CUSTOM_BT_COEXIST_CTRL, + DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, +#endif + */ + + /* + {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + {OID_CUSTOM_PATTERN_CONFIG, + DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUC_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, + {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, + {OID_CUSTOM_VOIP_SETUP, + DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, + {OID_CUSTOM_ADD_TS, + DISP_STRING("OID_CUSTOM_ADD_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, + {OID_CUSTOM_DEL_TS, + DISP_STRING("OID_CUSTOM_DEL_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, + */ + + /* +#if CFG_LP_PATTERN_SEARCH_SLT + {OID_CUSTOM_SLT, + DISP_STRING("OID_CUSTOM_SLT"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, +#endif + + {OID_CUSTOM_ROAMING_EN, + DISP_STRING("OID_CUSTOM_ROAMING_EN"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + {OID_CUSTOM_WMM_PS_TEST, + DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, + {OID_CUSTOM_COUNTRY_STRING, + DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, + +#if CFG_SUPPORT_802_11D + {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, +#endif + + {OID_CUSTOM_GPIO2_MODE, + DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + {OID_CUSTOM_CONTINUOUS_POLL, + DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, + {OID_CUSTOM_DISABLE_BEACON_DETECTION, + DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, + */ + + /* WPS */ + /* + {OID_CUSTOM_DISABLE_PRIVACY_CHECK, + DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, + */ + + {OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMcrRead, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMcrWrite}, + + {OID_CUSTOM_EEPROM_RW, + DISP_STRING("OID_CUSTOM_EEPROM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryEepromRead, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetEepromWrite}, + + {OID_CUSTOM_SW_CTRL, + DISP_STRING("OID_CUSTOM_SW_CTRL"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySwCtrlRead, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSwCtrlWrite}, + + {OID_CUSTOM_MEM_DUMP, + DISP_STRING("OID_CUSTOM_MEM_DUMP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMemDump, + NULL}, + + {OID_CUSTOM_TEST_MODE, + DISP_STRING("OID_CUSTOM_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidRftestSetTestMode}, + + /* + {OID_CUSTOM_TEST_RX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, + NULL}, + {OID_CUSTOM_TEST_TX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + NULL}, + */ + {OID_CUSTOM_ABORT_TEST_MODE, + DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidRftestSetAbortTestMode}, + {OID_CUSTOM_MTK_WIFI_TEST, + DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidRftestSetAutoTest}, + + /* OID_CUSTOM_EMULATION_VERSION_CONTROL */ + + /* BWCS */ +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {OID_CUSTOM_BWCS_CMD, + DISP_STRING("OID_CUSTOM_BWCS_CMD"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PTA_IPC_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBT, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBT}, +#endif + +/* {OID_CUSTOM_SINGLE_ANTENNA, + DISP_STRING("OID_CUSTOM_SINGLE_ANTENNA"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBtSingleAntenna, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtSingleAntenna}, + {OID_CUSTOM_SET_PTA, + DISP_STRING("OID_CUSTOM_SET_PTA"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPta, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPta}, + */ + + { OID_CUSTOM_MTK_NVRAM_RW, + DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryNvramRead, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetNvramWrite }, + + { OID_CUSTOM_CFG_SRC_TYPE, + DISP_STRING("OID_CUSTOM_CFG_SRC_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_CFG_SRC_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCfgSrcType, + NULL }, + + { OID_CUSTOM_EEPROM_TYPE, + DISP_STRING("OID_CUSTOM_EEPROM_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_EEPROM_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryEepromType, + NULL }, + +#if CFG_SUPPORT_WAPI + {OID_802_11_WAPI_MODE, + DISP_STRING("OID_802_11_WAPI_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWapiMode}, + {OID_802_11_WAPI_ASSOC_INFO, + DISP_STRING("OID_802_11_WAPI_ASSOC_INFO"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWapiAssocInfo}, + {OID_802_11_SET_WAPI_KEY, + DISP_STRING("OID_802_11_SET_WAPI_KEY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_WPI_KEY_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWapiKey}, +#endif + +#if CFG_SUPPORT_WPS2 + {OID_802_11_WSC_ASSOC_INFO, + DISP_STRING("OID_802_11_WSC_ASSOC_INFO"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWSCAssocInfo}, +#endif +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatching function for private ioctl region (SIOCIWFIRSTPRIV ~ +* SIOCIWLASTPRIV). +* +* \param[in] prNetDev Net device requested. +* \param[in] prIfReq Pointer to ifreq structure. +* \param[in] i4Cmd Command ID between SIOCIWFIRSTPRIV and SIOCIWLASTPRIV. +* +* \retval 0 for success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_support_ioctl ( + IN struct net_device *prNetDev, + IN OUT struct ifreq *prIfReq, + IN int i4Cmd + ) +{ + /* prIfReq is verified in the caller function wlanDoIOCTL() */ + struct iwreq *prIwReq = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + + /* prDev is verified in the caller function wlanDoIOCTL() */ + + /* Prepare the call */ + rIwReqInfo.cmd = (__u16)i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case IOCTL_SET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_set_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *) &(prIwReq->u)); + + case IOCTL_GET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_get_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *) &(prIwReq->u)); + + case IOCTL_SET_STRUCT: + case IOCTL_SET_STRUCT_FOR_EM: + return priv_set_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *) &(prIwReq->u)); + + case IOCTL_GET_STRUCT: + return priv_get_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *) &(prIwReq->u)); + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +}/* priv_support_ioctl */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_set_int ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_PTA_IPC_T prPtaIpc; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_MODE: + //printk("TestMode=%ld\n", pu4IntBuf[1]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_MODE; + } + else if (pu4IntBuf[1] == 0) { + prNdisReq->ndisOidCmd = OID_CUSTOM_ABORT_TEST_MODE; + } + else { + status = 0; + break; + } + prNdisReq->inNdisOidlength = 0; + prNdisReq->outNdisOidLength = 0; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + case PRIV_CMD_TEST_CMD: + //printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + //printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY && + pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) { + prGlueInfo->fgMcrAccessAllowed = TRUE; + } + status = 0; + break; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; +#endif + + case PRIV_CMD_SW_CTRL: + //printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + + #if 0 + case PRIV_CMD_BEACON_PERIOD: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), + &u4BufLen); + break; + #endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + case PRIV_CMD_CSUM_OFFLOAD: + { + UINT_32 u4CSUMFlags; + + + if (pu4IntBuf[1] == 1) { + u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + } + else if (pu4IntBuf[1] == 0) { + u4CSUMFlags = 0; + } + else { + return -EINVAL; + } + + if (kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID)&u4CSUMFlags, + sizeof(UINT_32), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen + ) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) { + prNetDev->features |= NETIF_F_HW_CSUM; + } else if (pu4IntBuf[1] == 0) { + prNetDev->features &= ~NETIF_F_HW_CSUM; + } + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + break; + + case PRIV_CMD_WMM_PS: + { + PARAM_CUSTOM_WMM_PS_TEST_STRUC_T rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (UINT_8)pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8)pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (UINT_8)pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, + wlanoidSetWiFiWmmPsTest, + (PVOID)&rWmmPsTest, + sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUC_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + } + break; + + #if 0 + case PRIV_CMD_ADHOC_MODE: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAdHocMode, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), + &u4BufLen); + break; + #endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, ("pu4IntBuf[1] = %x, size of PTA_IPC_T = %d.\n", pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T))); + + prPtaIpc = (P_PTA_IPC_T) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); + prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); + prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, ("BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], + prPtaIpc->u.aucBTPParams[1], + prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3])); + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, + (PVOID)&aucOidBuf[0], + u4CmdLen, + &u4BufLen); +#endif + + status = wlanoidSetBT(prGlueInfo->prAdapter, + (PVOID)&aucOidBuf[0], + sizeof(PARAM_PTA_IPC_T), + &u4BufLen); + + if (WLAN_STATUS_SUCCESS != status) { + status = -EFAULT; + } + + break; + + case PRIV_CMD_BAND_CONFIG: + { + DBGLOG(INIT, INFO, ("CMD set_band=%u\n", pu4IntBuf[1])); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: + { + PARAM_CUSTOM_P2P_SET_STRUC_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; + + if(!rSetP2P.u4Enable) { + p2pNetUnregister(prGlueInfo, TRUE); + } + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pMode, + (PVOID)&rSetP2P, /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + if(rSetP2P.u4Enable) { + p2pNetRegister(prGlueInfo, TRUE); + } + + + } + break; +#endif + + default: + return -EOPNOTSUPP; + } + + return status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_get_int ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + INT_32 ch[50]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_CMD: + //printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + //printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); + prIwReqData->mode = *(PUINT_32)&prNdisReq->ndisOidContent[4]; + /* + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], 4)) { + printk(KERN_NOTICE "priv_get_int() copy_to_user oidBuf fail(3)\n"); + return -EFAULT; + } + */ + } + return status; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + //printk("addr=0x%08lx\n", pu4IntBuf[1]); + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + //printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); + prIwReqData->mode = *(PUINT_32)&prNdisReq->ndisOidContent[4]; + } + return status; +#endif + + case PRIV_CMD_DUMP_MEM: + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + +#if 1 + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } +#endif + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MEM_DUMP; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + prIwReqData->mode = *(PUINT_32)&prNdisReq->ndisOidContent[0]; + } + return status; + + case PRIV_CMD_SW_CTRL: + //printk(" addr=0x%08lx\n", pu4IntBuf[1]); + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + //printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); + prIwReqData->mode = *(PUINT_32)&prNdisReq->ndisOidContent[4]; + } + return status; + + #if 0 + case PRIV_CMD_BEACON_PERIOD: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + (PVOID)pu4IntBuf, + sizeof(UINT_32), + &u4BufLen); + return status; + + case PRIV_CMD_POWER_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + (PVOID)pu4IntBuf, + sizeof(UINT_32), + &u4BufLen); + return status; + + case PRIV_CMD_ADHOC_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAdHocMode, + (PVOID)pu4IntBuf, + sizeof(UINT_32), + &u4BufLen); + return status; + #endif + + case PRIV_CMD_BAND_CONFIG: + DBGLOG(INIT, INFO, ("CMD get_band=\n")); + prIwReqData->mode = 0; + return status; + + default: + break; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i, j = 0; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + RF_CHANNEL_INFO_T aucChannelList[50]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + + if (kalIsAPmode(prGlueInfo)) { + for (i = 0; i < NumOfChannel; i++) { + if ((aucChannelList[i].ucChannelNum <= 13) || + (aucChannelList[i].ucChannelNum == 36 || aucChannelList[i].ucChannelNum == 40 || + aucChannelList[i].ucChannelNum == 44 || aucChannelList[i].ucChannelNum == 48)) { + ch[j] = (INT_32)aucChannelList[i].ucChannelNum; + j++; + } + } + } + else { + for (j = 0; j < NumOfChannel; j++) { + ch[j] = (INT_32)aucChannelList[j].ucChannelNum; + } + } + + prIwReqData->data.length = j; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel*sizeof(INT_32))) { + return -EFAULT; + } + else + return status; + } + default: + return -EOPNOTSUPP; + } + + return status; +} /* priv_get_int */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int array handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_set_ints ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ) +{ + UINT_32 u4SubCmd, u4BufLen; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_SET_TXPWR_CTRL_T prTxpwr; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: + { + INT_32 *setting = prIwReqData->data.pointer; + UINT_16 i; + +#if 0 + printk("Tx power num = %d\n", prIwReqData->data.length); + + printk("Tx power setting = %d %d %d %d\n", + setting[0], setting[1], setting[2], setting[3]); +#endif + prTxpwr = &prGlueInfo->rTxPwr; + if (setting[0] == 0 && prIwReqData->data.length == 4 /* argc num */) { + /* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ + if (setting[1] == 1 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = setting[3]; + } + if (setting[1] == 2 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = setting[3]; + } + if (setting[1] == 3 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = setting[3]; + } + if (setting[1] == 4 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GBowPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GBowPwrOffset = setting[3]; + } + } + else if (setting[0] == 1 && prIwReqData->data.length == 2) { + prTxpwr->ucConcurrencePolicy = setting[1]; + } + else if (setting[0] == 2 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i=0; i<14; i++) + prTxpwr->acTxPwrLimit2G[i] = setting[2]; + } + else if (setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[setting[1] - 1] = setting[2]; + } + else if (setting[0] == 3 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i=0; i<4; i++) + prTxpwr->acTxPwrLimit5G[i] = setting[2]; + } + else if (setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[setting[1] - 1] = setting[2]; + } + else if (setting[0] == 4 && prIwReqData->data.length == 2) { + if (setting[1] == 0) { + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + } + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxPower, + prTxpwr, + sizeof(SET_TXPWR_CTRL_T), + TRUE, + FALSE, + FALSE, + FALSE, + &u4BufLen); + } + else + return -EFAULT; + } + return status; + default: + break; + } + + return status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int array handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_get_ints ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ) +{ + UINT_32 u4SubCmd; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + INT_32 ch[50]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + RF_CHANNEL_INFO_T aucChannelList[50]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + + for (i = 0; i < NumOfChannel; i++) { + ch[i] = (INT_32)aucChannelList[i].ucChannelNum; + } + + prIwReqData->data.length = NumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel*sizeof(INT_32))) { + return -EFAULT; + } + else + return status; + } + default: + break; + } + + return status; +} /* priv_get_int */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set structure handler. +* +* \param[in] pDev Net device requested. +* \param[in] prIwReqData Pointer to iwreq_data structure. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_set_struct ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ) +{ + UINT_32 u4SubCmd = 0; + int status = 0; + //WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4CmdLen = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + PUINT_32 pu4IntBuf = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + //ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + //ASSERT(pcExtra); + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwReqData)) { + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + +#if 0 + printk(KERN_INFO DRV_NAME"priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, + u4SubCmd + ); +#endif + + switch (u4SubCmd) { +#if 0 //PTA_ENABLED + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); + if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) { + return -EFAULT; + } + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; //return -EFAULT; + break; + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBtCoexistCtrl, + (PVOID)&aucOidBuf[0], + u4CmdLen, + &u4BufLen); + if (WLAN_STATUS_SUCCESS != rStatus) { + status = -EFAULT; + } + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_PTA_IPC_T) >= u4CmdLen); + if (sizeof(PARAM_PTA_IPC_T) < u4CmdLen) { + return -EFAULT; + } +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, ("ucCmdLen = %d, size of PTA_IPC_T = %d, prIwReqData->data = 0x%x.\n", u4CmdLen, sizeof(PARAM_PTA_IPC_T), prIwReqData->data)); + + DBGLOG(REQ, INFO, ("priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, + u4SubCmd + )); + + DBGLOG(REQ, INFO, ("*pcExtra = 0x%x\n", *pcExtra)); + #endif + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; //return -EFAULT; + break; + } +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, ("priv_set_struct(): BWCS CMD = %02x%02x%02x%02x\n", + aucOidBuf[2], aucOidBuf[3], aucOidBuf[4], aucOidBuf[5])); +#endif + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, + (PVOID)&aucOidBuf[0], + u4CmdLen, + &u4BufLen); +#endif + +#if 1 + status = wlanoidSetBT(prGlueInfo->prAdapter, + (PVOID)&aucOidBuf[0], + u4CmdLen, + &u4BufLen); +#endif + + if (WLAN_STATUS_SUCCESS != status) { + status = -EFAULT; + } + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: + { + /* retrieve IE for Probe Request */ + if (prIwReqData->data.length > 0) { + if (copy_from_user(prGlueInfo->aucWSCIE, prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + break; + } + prGlueInfo->u2WSCIELen = prIwReqData->data.length; + } + else { + prGlueInfo->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, ("pcExtra buffer is valid\n")); + } + else + DBGLOG(REQ, INFO, ("pcExtra 0x%p\n", pcExtra)); + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, (P_NDIS_TRANSPORT_STRUCT)&aucOidBuf[0], &u4BufLen); + /* Copy result to user space */ + ((P_NDIS_TRANSPORT_STRUCT)&aucOidBuf[0])->outNdisOidLength = u4BufLen; + + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, ("copy_to_user oidBuf fail\n")); + status = -EFAULT; + } + + break; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32)prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + //kalMemCopy(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, 8); + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + break; + } + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get struct handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] cmd Private sub-command. +* +* \retval 0 For success. +* \retval -EFAULT If copy from user space buffer fail. +* \retval -EOPNOTSUPP Parameter "cmd" not recognized. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_get_struct ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ) +{ + UINT_32 u4SubCmd = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq= NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + PUINT_32 pu4IntBuf = NULL; + int status = 0; + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, ("priv_get_struct(): invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData)); + return -EINVAL; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, ("priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev)))); + return -EINVAL; + } + +#if 0 + printk(KERN_INFO DRV_NAME"priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, + u4SubCmd + ); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + sizeof(NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, ("priv_get_struct() copy_from_user oidBuf fail\n")); + return -EFAULT; + } + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT)&aucOidBuf[0]; +#if 0 + printk(KERN_NOTICE "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, + pIwReq->u.data.length, + ndisReq->ndisOidCmd, + ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, ("priv_get_struct() copy_to_user oidBuf fail(1)\n")); + return -EFAULT; + } + return 0; + } + else { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, ("priv_get_struct() copy_to_user oidBuf fail(2)\n")); + } + return -EFAULT; + } + break; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32)prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, ("priv_get_struct() copy_from_user oidBuf fail\n")); + return -EFAULT; + } + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + //printk("len=%d Result=%08lx\n", u4BufLen, *(PUINT_32)&prNdisReq->ndisOidContent[4]); + + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], + 4 /* OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent)*/)) { + DBGLOG(REQ, INFO, ("priv_get_struct() copy_to_user oidBuf fail(2)\n")); + } + } + return 0; + break; + default: + DBGLOG(REQ, WARN, ("get struct cmd:0x%lx\n", u4SubCmd)); + return -EOPNOTSUPP; + } +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis ( + IN struct net_device *prNetDev, + IN NDIS_TRANSPORT_STRUCT* prNdisReq, + OUT PUINT_32 pu4OutputLen + ) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4SetInfoLen = 0; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, ("priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen)); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, ("priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev)))); + return -EINVAL; + } + +#if 0 + printk(KERN_INFO DRV_NAME"priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd + ); +#endif + + if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry)) { + //WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); + return -EOPNOTSUPP; + } + + if (NULL == prWlanReqEntry->pfOidSetHandler) { + //WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); + return -EOPNOTSUPP; + } + +#if 0 + printk(KERN_INFO DRV_NAME"priv_set_ndis(): %s\n", + prWlanReqEntry->pucOidName + ); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, ("Set %s: Invalid length (current=%ld, needed=%ld)\n", + prWlanReqEntry->pucOidName, + prNdisReq->inNdisOidlength, + prWlanReqEntry->u4InfoBufLen)); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + &u4SetInfoLen); + } + else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + &u4SetInfoLen); + } + else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core*/ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC)prWlanReqEntry->pfOidSetHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + } + else { + DBGLOG(REQ, INFO, ("priv_set_ndis(): unsupported OID method:0x%x\n", + prWlanReqEntry->eOidMethod)); + return -EOPNOTSUPP; + } + + *pu4OutputLen = u4SetInfoLen; + + switch (status) { + case WLAN_STATUS_SUCCESS: + break; + + case WLAN_STATUS_INVALID_LENGTH: + //WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", + // prWlanReqEntry->pucOidName, + //prNdisReq->inNdisOidlength, + //u4SetInfoLen)); + break; + } + + if (WLAN_STATUS_SUCCESS != status) { + return -EFAULT; + } + + return 0; +} /* priv_set_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a query operation for a single OID. Basically we +* return information about the current state of the OID in question. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL invalid input parameters +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_get_ndis ( + IN struct net_device *prNetDev, + IN NDIS_TRANSPORT_STRUCT* prNdisReq, + OUT PUINT_32 pu4OutputLen + ) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + UINT_32 u4BufLen = 0; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, ("priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen)); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, ("priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev)))); + return -EINVAL; + } + +#if 0 + printk(KERN_INFO DRV_NAME"priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd + ); +#endif + + if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry)) { + //WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); + return -EOPNOTSUPP; + } + + + if (NULL == prWlanReqEntry->pfOidQueryHandler) { + //WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); + return -EOPNOTSUPP; + } + +#if 0 + printk(KERN_INFO DRV_NAME"priv_get_ndis(): %s\n", + prWlanReqEntry->pucOidName + ); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + //WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", + //prWlanReqEntry->pucOidName, + //prNdisReq->inNdisOidlength, + //prWlanReqEntry->u4InfoBufLen)); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + &u4BufLen); + } + else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + &u4BufLen); + } + else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core*/ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC)prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); + } + else { + DBGLOG(REQ, INFO, ("priv_set_ndis(): unsupported OID method:0x%x\n", + prWlanReqEntry->eOidMethod)); + return -EOPNOTSUPP; + } + + *pu4OutputLen = u4BufLen; + + switch (status) { + case WLAN_STATUS_SUCCESS: + break; + + case WLAN_STATUS_INVALID_LENGTH: + //WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", + // prWlanReqEntry->pucOidName, + //prNdisReq->inNdisOidlength, + //u4BufLen)); + break; + } + + if (WLAN_STATUS_SUCCESS != status) { + return -EOPNOTSUPP; + } + + return 0; +} /* priv_get_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search desired OID. +* +* \param rOid[in] Desired NDIS_OID +* \param ppWlanReqEntry[out] Found registered OID entry +* +* \retval TRUE: Matched OID is found +* \retval FALSE: No matched OID is found +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +reqSearchSupportedOidEntry ( + IN UINT_32 rOid, + OUT P_WLAN_REQ_ENTRY *ppWlanReqEntry + ) +{ + INT_32 i, j, k; + + i = 0; + j = NUM_SUPPORTED_OIDS - 1; + + while (i <= j) { + k = (i + j) / 2; + + if (rOid == arWlanOidReqTable[k].rOid) { + *ppWlanReqEntry = &arWlanOidReqTable[k]; + return TRUE; + } else if (rOid < arWlanOidReqTable[k].rOid) { + j = k - 1; + } else { + i = k + 1; + } + } + + return FALSE; +} /* reqSearchSupportedOidEntry */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the radio configuration used in IBSS +* mode and RF test mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[out] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtQueryConfiguration ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ) +{ + P_PARAM_802_11_CONFIG_T prQueryConfig = (P_PARAM_802_11_CONFIG_T)pvQueryBuffer; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + + DEBUGFUNC("wlanoidQueryConfiguration"); + + + ASSERT(prGlueInfo); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_CONFIG_T); + if (u4QueryBufferLen < sizeof(PARAM_802_11_CONFIG_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + kalMemZero(prQueryConfig, sizeof(PARAM_802_11_CONFIG_T)); + + /* Update the current radio configuration. */ + prQueryConfig->u4Length = sizeof(PARAM_802_11_CONFIG_T); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prQueryConfig->u4BeaconPeriod, + sizeof(UINT_32), + TRUE, + TRUE, + &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + &prQueryConfig->u4BeaconPeriod, + sizeof(UINT_32), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, + sizeof(UINT_32), + TRUE, + TRUE, + &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, + sizeof(UINT_32), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, + sizeof(UINT_32), + TRUE, + TRUE, + &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, + sizeof(UINT_32), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + + prQueryConfig->rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + return rStatus; + +} /* end of reqExtQueryConfiguration() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the radio configuration used in IBSS +* mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetConfiguration ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_PARAM_802_11_CONFIG_T prNewConfig = (P_PARAM_802_11_CONFIG_T)pvSetBuffer; + UINT_32 u4SetInfoLen = 0; + + DEBUGFUNC("wlanoidSetConfiguration"); + + + ASSERT(prGlueInfo); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_802_11_CONFIG_T); + + if (u4SetBufferLen < *pu4SetInfoLen) { + return WLAN_STATUS_INVALID_LENGTH; + } + + /* OID_802_11_CONFIGURATION. If associated, NOT_ACCEPTED shall be returned. */ + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_NOT_ACCEPTED; + } + + ASSERT(pvSetBuffer); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, + sizeof(UINT_32), + FALSE, + TRUE, + &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, + sizeof(UINT_32), + &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, + sizeof(UINT_32), + FALSE, + TRUE, + &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, + sizeof(UINT_32), + &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetFrequency, + &prNewConfig->u4DSConfig, + sizeof(UINT_32), + FALSE, + TRUE, + &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetFrequency, + &prNewConfig->u4DSConfig, + sizeof(UINT_32), + &u4SetInfoLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + return rStatus; + } + + return rStatus; + +} /* end of reqExtSetConfiguration() */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set beacon detection function enable/disable state +* This is mainly designed for usage under BT inquiry state (disable function). +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetAcpiDevicePowerState ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + /* WIFI is enabled, when ACPI is D0 (ParamDeviceStateD0 = 1). And vice versa */ + + //rStatus = wlanSetInformation(prGlueInfo->prAdapter, + // wlanoidSetAcpiDevicePowerState, + // pvSetBuffer, + // u4SetBufferLen, + // pu4SetInfoLen); + return rStatus; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c new file mode 100755 index 000000000000..4322fa303a71 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c @@ -0,0 +1,33 @@ +/****************************************************************************** +*[File] mt6516-evb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* dummy file for build system +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + + +/* +** $Log: mt6516-evb.c $ + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug message + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** +*/ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h new file mode 100755 index 000000000000..23eac4684d56 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h @@ -0,0 +1,225 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 $ +*/ + +/*! \file "hif.h" + \brief Functions for the driver to register bus and setup the IRQ + + Functions for the driver to register bus and setup the IRQ +*/ + + + +/* +** $Log: hif.h $ + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 17 2010 cp.wu + * NULL + * add ENE SDIO host workaround for x86 linux platform. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\4 2009-10-20 17:38:28 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw. +** \main\maintrunk.MT5921\3 2009-09-28 20:19:20 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\2 2009-08-18 22:57:05 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\2 2008-09-22 23:18:17 GMT mtk01461 +** Update driver for code review +** Revision 1.1 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +*/ + +#ifndef _HIF_H +#define _HIF_H + + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#endif + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define SDIO_X86_WORKAROUND_WRITE_MCR 0x00C4 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +typedef struct _GL_HIF_INFO_T { +#if MTK_WCN_HIF_SDIO + MTK_WCN_HIF_SDIO_CLTCTX cltCtx; + const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo; +#else + struct sdio_func *func; +#endif + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; +} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; + + +#if CFG_DBG_GPIO_PINS + +extern void +mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod); + + +/* Platform DEPENDENT configurations: MT6516 GPIO pin name */ +#define GPIO_6516(x) (GPIO##x) +#define GPIO_PLATFORM(x) GPIO_6516(x) + +/* Platform independent configurations */ +#define DBG_TIE_DIR 0x40000000UL +#define DBG_LOW 0x0UL +#define DBG_HIGH 0x1UL +#define DBG_TIE_LOW (DBG_TIE_DIR | DBG_LOW) +#define DBG_TIE_HIGH (DBG_TIE_DIR | DBG_HIGH) + +#define DBG_TOGGLE(x) (0x80000000UL | x) +#define DBG_TOGGLE_NUM(x) (x & 0xFFF) +#define GPIO_INVALID 0xFFFF + +typedef enum { + IDX_ERR = 0, + IDX_TX_THREAD, + IDX_TX_REQ, + IDX_TX_PORT_WRITE, + IDX_STP_MTX_BT, + IDX_STP_MTX_FM, /* 5 */ + IDX_STP_MTX_GPS, + IDX_STP_MTX_WIFI, + IDX_STP_MTX_WMT, + IDX_LOOP_CNT, + IDX_NO_BUF, /*10 */ + IDX_BT_TX, + IDX_BT_RX, + IDX_GPS_RX, + IDX_GPS_2, + IDX_GPS_3, + IDX_GPS_TX, + IDX_STP_MAX +} DBG_PIN; + +#define DBG_MTX_OFFSET (IDX_STP_MTX_BT) /* index of mutex0 */ +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS +glRegisterBus( + probe_card pfProbe, + remove_card pfRemove + ); + +VOID +glUnregisterBus( + remove_card pfRemove + ); + +VOID +glSetHifInfo ( + P_GLUE_INFO_T prGlueInfo, + UINT_32 u4Cookie + ); + +VOID +glClearHifInfo ( + P_GLUE_INFO_T prGlueInfo + ); + +BOOL +glBusInit ( + PVOID pvData + ); + +VOID +glBusRelease ( + PVOID pData + ); + +INT_32 +glBusSetIrq ( + PVOID pvData, + PVOID pfnIsr, + PVOID pvCookie + ); + +VOID +glBusFreeIrq ( + PVOID pvData, + PVOID pvCookie + ); + +VOID +glSetPowerState ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 ePowerMode + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h new file mode 100755 index 000000000000..9fac1e066b0f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h @@ -0,0 +1,290 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 $ +*/ + +/*! \file "hif_sdio.h" + \brief + + +*/ + +/* +** $Log: $ + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 05 02 2012 terry.wu + * NULL + * Fix build error if HAVE_AEE_FEATURE = n + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 07 25 2010 george.kuo + * + * Move hif_sdio driver to linux directory. + * + * 07 23 2010 george.kuo + * + * Add MT6620 driver source tree + * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver. +** +** +*/ + +#ifndef _HIF_SDIO_H +#define _HIF_SDIO_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_SDIO_DEBUG (0) /* 0:trun off debug msg and assert, 1:trun off debug msg and assert */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "mtk_porting.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CFG_CLIENT_COUNT (9) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +#define HIF_SDIO_LOG_LOUD 4 +#define HIF_SDIO_LOG_DBG 3 +#define HIF_SDIO_LOG_INFO 2 +#define HIF_SDIO_LOG_WARN 1 +#define HIF_SDIO_LOG_ERR 0 + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Function info provided by client driver */ +typedef struct _MTK_WCN_HIF_SDIO_FUNCINFO MTK_WCN_HIF_SDIO_FUNCINFO; + +/* Client context provided by hif_sdio driver for the following function call */ +typedef UINT32 MTK_WCN_HIF_SDIO_CLTCTX; + +/* Callback functions provided by client driver */ +typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); +typedef INT32 (*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX); +typedef INT32 (*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX); + +/* Function info provided by client driver */ +struct _MTK_WCN_HIF_SDIO_FUNCINFO { + UINT16 manf_id; /* TPLMID_MANF: manufacturer ID */ + UINT16 card_id; /* TPLMID_CARD: card ID */ + UINT16 func_num; /* Function Number */ + UINT16 blk_sz; /* Function block size */ +}; + +/* Client info provided by client driver */ +typedef struct _MTK_WCN_HIF_SDIO_CLTINFO { + const MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */ + UINT32 func_tbl_size; /* supported function table info element number */ + MTK_WCN_HIF_SDIO_PROBE hif_clt_probe; /* callback function for probing */ + MTK_WCN_HIF_SDIO_REMOVE hif_clt_remove; /* callback function for removing */ + MTK_WCN_HIF_SDIO_IRQ hif_clt_irq; /* callback function for interrupt handling */ +} MTK_WCN_HIF_SDIO_CLTINFO; + +/* function info provided by registed function */ +typedef struct _MTK_WCN_HIF_SDIO_REGISTINFO { + const MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */ + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */ +} MTK_WCN_HIF_SDIO_REGISTINFO; + +/* Card info provided by probed function */ +typedef struct _MTK_WCN_HIF_SDIO_PROBEINFO { + struct sdio_func* func; /* probed sdio function pointer */ + void* private_data_p; /* clt's private data pointer */ + MTK_WCN_BOOL on_by_wmt; /* TRUE: on by wmt, FALSE: not on by wmt */ + /* added for sdio irq sync and mmc single_irq workaround */ + MTK_WCN_BOOL sdio_irq_enabled; /* TRUE: can handle sdio irq; FALSE: no sdio irq handling */ + INT8 clt_idx; /* registered function table info element number (initial value is -1) */ +} MTK_WCN_HIF_SDIO_PROBEINFO; + + +/* work queue info needed by worker */ +typedef struct _MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO { + struct work_struct probe_work; /* work queue structure */ + MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p; /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */ + INT8 probe_idx; /* probed function table info element number (initial value is -1) */ +} MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO; + +/* error code returned by hif_sdio driver (use NEGATIVE number) */ +typedef enum { + HIF_SDIO_ERR_SUCCESS = 0, + HIF_SDIO_ERR_FAIL = HIF_SDIO_ERR_SUCCESS - 1, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM = HIF_SDIO_ERR_FAIL - 1, + HIF_SDIO_ERR_DUPLICATED = HIF_SDIO_ERR_INVALID_PARAM - 1, + HIF_SDIO_ERR_UNSUP_MANF_ID = HIF_SDIO_ERR_DUPLICATED - 1, + HIF_SDIO_ERR_UNSUP_CARD_ID = HIF_SDIO_ERR_UNSUP_MANF_ID - 1, + HIF_SDIO_ERR_INVALID_FUNC_NUM = HIF_SDIO_ERR_UNSUP_CARD_ID - 1, + HIF_SDIO_ERR_INVALID_BLK_SZ = HIF_SDIO_ERR_INVALID_FUNC_NUM - 1, + HIF_SDIO_ERR_NOT_PROBED = HIF_SDIO_ERR_INVALID_BLK_SZ - 1, + HIF_SDIO_ERR_ALRDY_ON = HIF_SDIO_ERR_NOT_PROBED -1, + HIF_SDIO_ERR_ALRDY_OFF = HIF_SDIO_ERR_ALRDY_ON -1, + HIF_SDIO_ERR_CLT_NOT_REG = HIF_SDIO_ERR_ALRDY_OFF - 1, +} MTK_WCN_HIF_SDIO_ERR ; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*! + * \brief A macro used to describe an SDIO function + * + * Fill an MTK_WCN_HIF_SDIO_FUNCINFO structure with function-specific information + * + * \param manf the 16 bit manufacturer id + * \param card the 16 bit card id + * \param func the 16 bit function number + * \param b_sz the 16 bit function block size + */ +#define MTK_WCN_HIF_SDIO_FUNC(manf, card, func, b_sz) \ + .manf_id = (manf), .card_id = (card), .func_num = (func), .blk_sz = (b_sz) + +#define HIF_SDIO_LOUD_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_LOUD) { printk(KERN_INFO SDIO_TAG"[L]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_DBG_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_DBG) { printk(KERN_INFO SDIO_TAG"[D]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_INFO_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_INFO) { printk(KERN_INFO SDIO_TAG"[I]%s:" fmt, __FUNCTION__ ,##arg);} +#define HIF_SDIO_WARN_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_WARN) { printk(KERN_WARNING SDIO_TAG"[W]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} +#define HIF_SDIO_ERR_FUNC(fmt, arg...) if (gHifSdioDbgLvl >= HIF_SDIO_LOG_ERR) { printk(KERN_WARNING SDIO_TAG"[E]%s(%d):" fmt, __FUNCTION__ , __LINE__, ##arg);} + + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define HIF_SDIO_ASSERT(expr) if ( !(expr) ) { \ + + printk("assertion failed! %s[%d]: %s\n",\ + __FUNCTION__, __LINE__, #expr); \ + BUG_ON( !(expr) );\ + } +#else +#define HIF_SDIO_ASSERT(expr) do {} while(0) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*! + * \brief MTK hif sdio client registration function + * + * Client uses this function to do hif sdio registration + * + * \param pinfo a pointer of client's information + * + * \retval 0 register successfully + * \retval < 0 error code + */ +extern INT32 mtk_wcn_hif_sdio_client_reg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ); + +extern INT32 mtk_wcn_hif_sdio_client_unreg ( + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo + ); + +extern INT32 mtk_wcn_hif_sdio_readb ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT8 pvb + ); + +extern INT32 mtk_wcn_hif_sdio_writeb ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT8 vb + ); + +extern INT32 mtk_wcn_hif_sdio_readl ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pvl + ); + +extern INT32 mtk_wcn_hif_sdio_writel ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + UINT32 vl + ); + +extern INT32 mtk_wcn_hif_sdio_read_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ); + +extern INT32 mtk_wcn_hif_sdio_write_buf ( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + UINT32 offset, + PUINT32 pbuf, + UINT32 len + ); + +extern void mtk_wcn_hif_sdio_set_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + void* private_data_p + ); + +extern void* mtk_wcn_hif_sdio_get_drvdata( + MTK_WCN_HIF_SDIO_CLTCTX ctx + ); + +extern void mtk_wcn_hif_sdio_get_dev( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + struct device **dev + ); +extern void mtk_wcn_hif_sdio_enable_irq( + MTK_WCN_HIF_SDIO_CLTCTX ctx, + MTK_WCN_BOOL enable + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ + + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h new file mode 100755 index 000000000000..37f96be599e0 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h @@ -0,0 +1,52 @@ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* Type definition for signed integers */ +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT32, *PINT32; + +/* Type definition for unsigned integers */ +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; + +//typedef void VOID, *PVOID; + +typedef int MTK_WCN_BOOL; +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +typedef int MTK_WCN_MUTEX; + +typedef int MTK_WCN_TIMER; + +/* system APIs */ +/* mutex */ +typedef MTK_WCN_MUTEX (*MUTEX_CREATE)(const char * const name); +typedef INT32 (*MUTEX_DESTROY)(MTK_WCN_MUTEX mtx); +typedef INT32 (*MUTEX_LOCK)(MTK_WCN_MUTEX mtx); +typedef INT32 (*MUTEX_UNLOCK)(MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT32 (*DBG_PRINT)(const char *str, ...); +typedef INT32 (*DBG_ASSERT)(INT32 expr, const char *file, INT32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB)(void); +typedef MTK_WCN_TIMER (*TIMER_CREATE)(const char * const name); +typedef INT32 (*TIMER_DESTROY)(MTK_WCN_TIMER tmr); +typedef INT32 (*TIMER_START)(MTK_WCN_TIMER tmr, UINT32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT32 (*TIMER_STOP)(MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void* (*SYS_MEMCPY)(void *dest, const void *src, UINT32 n); +typedef void* (*SYS_MEMSET)(void *s, INT32 c, UINT32 n); +typedef INT32 (*SYS_SPRINTF)(char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c new file mode 100755 index 000000000000..152778964786 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c @@ -0,0 +1,1329 @@ +/****************************************************************************** +*[File] sdio.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* The program provides SDIO HIF driver +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + + +/* +** $Log: sdio.c $ + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 02 14 2012 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * include correct header file upon setting. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 09 20 2011 cp.wu + * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized + * 1. always show error message for SDIO bus errors. + * 2. reset bus error flag when re-initialization + * + * 08 17 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628 related definitions for Linux/Android driver. + * + * 05 18 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add device ID for MT5931. + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 18 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 11 15 2010 jeffrey.chang + * [WCXRP00000181] [MT6620 Wi-Fi][Driver] fix the driver message "GLUE_FLAG_HALT skip INT" during unloading + * Fix GLUE_FALG_HALT message which cause driver to hang + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * correct typo + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 19 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 08 21 2010 jeffrey.chang + * NULL + * 1) add sdio two setting + * 2) bug fix of sdio glue + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 18 2010 cp.wu + * NULL + * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86. + * + * 08 17 2010 cp.wu + * NULL + * add ENE SDIO host workaround for x86 linux platform. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Fix hotplug bug + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * clear sdio interrupt + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_os.h" + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +//#ifndef CONFIG_X86 modify by Nicolas Luo +#ifdef CONFIG_ARM +#include +#endif + + +#if defined(MT6620) + #include "mt6620_reg.h" +#elif defined(MT5931) + #include "mt5931_reg.h" +#elif defined(MT6628) + #include "mt6628_reg.h" +#endif + +#if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */ +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define HIF_SDIO_ERR_TITLE_STR "["CHIP_NAME"] SDIO Access Error!" +#define HIF_SDIO_ERR_DESC_STR "**SDIO Access Error**\n" + +#if MTK_WCN_HIF_SDIO + + +/* + * function prototypes + * + */ + +static INT32 +mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); + +static INT32 +mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX); +static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX); + +/* + * sdio function info table + */ + +static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = { +#if defined(MT6620) + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020a, 0x1, 512) }, + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020c, 0x2, 512) }, + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018a, 0x1, 512) }, + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018c, 0x2, 512) }, +#elif defined(MT5931) + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x5931, 0x1, 512) }, +#elif defined(MT6628) + { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6628, 0x1, 512) }, +#endif +}; + + +static MTK_WCN_HIF_SDIO_CLTINFO cltInfo = { + .func_tbl = funcInfo, + .func_tbl_size = sizeof(funcInfo)/sizeof(MTK_WCN_HIF_SDIO_FUNCINFO), + .hif_clt_probe = mtk_sdio_probe, + .hif_clt_remove = mtk_sdio_remove, + .hif_clt_irq = mtk_sdio_interrupt, +}; + +#else + +static const struct sdio_device_id mtk_sdio_ids[] = { +#if defined(MT6620) + { SDIO_DEVICE(0x037a, 0x020a) }, /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037a, 0x020b) }, /* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037a, 0x020c) }, /* Not an SDIO standard class device */ +#elif defined(MT5931) + { SDIO_DEVICE(0x037a, 0x5931) }, /* Not an SDIO standard class device */ +#elif defined(MT6628) + { SDIO_DEVICE(0x037a, 0x6628) }, /* Not an SDIO standard class device */ +#endif + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids); + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern KAL_WAKE_LOCK_T isr_wakelock; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static probe_card pfWlanProbe = NULL; +static remove_card pfWlanRemove = NULL; + + +#if (MTK_WCN_HIF_SDIO == 0) +static struct sdio_driver mtk_sdio_driver = { + .name = "wlan", /* "MTK SDIO WLAN Driver" */ + .id_table = mtk_sdio_ids, + .probe = NULL, + .remove = NULL, +}; +#endif + + +#if CFG_DBG_GPIO_PINS + +/* debug pins */ +UINT_32 dbgPinSTP[] = { + GPIO_PLATFORM(33)/* CMFLASH, IDX_ERR J613 */ + , GPIO_PLATFORM(62)/* EINT3, IDX_TX_THREAD */ + , GPIO_PLATFORM(80)/* SPI_CS_N, IDX_TX_REQ J613 */ + , GPIO_PLATFORM(81)/* SPI_SCK, IDX_TX_PORT_WRITE J613 */ + , GPIO_PLATFORM(17) /* CMRST, IDX_STP_MTX_BT J618 */ + , GPIO_PLATFORM(18) /* CMPDN, IDX_STP_MTX_FM J613 */ + , GPIO_PLATFORM(19) /* CMVREF,IDX_STP_MTX_GPS J613 */ + , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WIFI */ + , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WMT */ + , GPIO_PLATFORM(135) /* SCL2, IDX_LOOP_CNT J616 */ + , GPIO_PLATFORM(136) /* SDA2, IDX_NO_BUF J616 */ + , GPIO_PLATFORM(30) /* CAM_MECHSH0, IDX_BT_TX, J613 low-active */ + , GPIO_PLATFORM(31) /* CAM_MECHSH1, IDX_BT_RX, J613 low-active */ + , GPIO_PLATFORM(124) /* GPS_PWR_EN, ThreadDSPIn [GPS] */ + , GPIO_PLATFORM(125) /* GPS_SYNC, mtk_sys_msg_recv [GPS] */ + , GPIO_PLATFORM(21) /* GPS_EINT8, dump_nmea_data [GPS] */ + , GPIO_PLATFORM(29) /* CAM_STROBE, IDX_GPS_TX, J613 low-active */ + , GPIO_PLATFORM(20) /*CMHREF, J613 UNUSED */ +// , GPIO_6516(64) /* EINT5, REMOVED!!! for MT6620-Wi-Fi Int */ +// , GPIO_6516(122) /* BT_PWR_EN, REMOVED!!! for MT6620-PMU_EN */ +// , GPIO_6516(123) /* BT_RESET, REMOVED!!! for MT6620-RST */ +}; +#endif +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if CFG_DBG_GPIO_PINS +void debug_gpio_init(void) +{ + int i; + + for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) { + if (GPIO_INVALID == dbgPinSTP[i]) { + continue; + } + //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]); + mt_set_gpio_pull_enable(dbgPinSTP[i], 0); /* disable pull */ + mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_OUT); /* set output */ + mt_set_gpio_mode(dbgPinSTP[i], GPIO_MODE_00); /* set gpio mode */ + + /* toggle twice to check if ok: */ + mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */ + mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/ + mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */ + mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/ + } + //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__); +} + +void debug_gpio_deinit(void) +{ + int i; + for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) { + if (GPIO_INVALID == dbgPinSTP[i]) { + continue; + } + //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]); + mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN); + } + + //printk(KERN_INFO "[%s] k\n", __FUNCTION__); +} + +void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod) +{ + unsigned int i; + + if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) { + //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex); + return; + } + + if (dwIndex > IDX_STP_MAX) { + //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX); + } + + if (GPIO_INVALID == dbgPinSTP[dwIndex]) { + return; + } + + if (dwMethod & DBG_TIE_DIR) { + if (dwMethod & DBG_HIGH) { + mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE); + } + else { + mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO); + } + return; + } + + if (dwMethod & DBG_TOGGLE(0)) { + for (i = 0; i < DBG_TOGGLE_NUM(dwMethod); ++i) { + mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO); + mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE); + } + return; + } + + return; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +#if MTK_WCN_HIF_SDIO + +static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT32 ret = 0; + + prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx); + + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n"); + return (-HIF_SDIO_ERR_FAIL); + } + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); + ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return ret; + } + /*WCNCR 00002676*/ + KAL_WAKE_UNLOCK(NULL, &isr_wakelock); + KAL_WAKE_LOCK_TIMEOUT(NULL, &isr_wakelock, KAL_HZ/10); + ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag); + + /* when we got sdio interrupt, we wake up the tx servie thread*/ + wake_up_interruptible(&prGlueInfo->waitq); + + return ret; +} + +#else + +static unsigned int in_interrupt = 0; + +static void mtk_sdio_interrupt(struct sdio_func *func) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + int ret = 0; + + prGlueInfo = sdio_get_drvdata(func); + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n"); + return; + } + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); + return; + } + + sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + + #if 0 + wlanISR(prGlueInfo->prAdapter, TRUE); + + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n"); + } + else { + wlanIST(prGlueInfo->prAdapter); + } + #endif + + set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag); + + /* when we got sdio interrupt, we wake up the tx servie thread*/ + wake_up_interruptible(&prGlueInfo->waitq); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO probe function +* +* \param[in] func pointer to SDIO handle +* \param[in] id pointer to SDIO device id table +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +#if MTK_WCN_HIF_SDIO + +// FIXME: global variable +static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc; + + +static INT32 +mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo) +{ + INT32 ret = HIF_SDIO_ERR_SUCCESS; + + prFunc = prFuncInfo; + + if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) { + //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -(HIF_SDIO_ERR_FAIL); + } else { + //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret); + } + return ret; +} +#else +static int mtk_sdio_probe ( + struct sdio_func *func, + const struct sdio_device_id *id + ) +{ + int ret = 0; + int i = 0; + + //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n"); + + ASSERT(func); + ASSERT(id); + + //printk(KERN_INFO DRV_NAME "Basic struct size checking...\n"); + //printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command)); + //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request)); + //printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func)); + + //printk(KERN_INFO DRV_NAME "Card information checking...\n"); + //printk(KERN_INFO DRV_NAME "func = 0x%p\n", func); + //printk(KERN_INFO DRV_NAME "Number of info = %d:\n", func->card->num_info); + + for (i = 0; i < func->card->num_info; i++) { + //printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, func->card->info[i]); + } + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + + if (ret) { + //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n"); + goto out; + } + //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n"); + + if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) { + //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + } + else { +#if CFG_DBG_GPIO_PINS + //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__); + /* Debug pins initialization */ + debug_gpio_init(); +#endif + } + +out: + //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret); + return ret; +} +#endif + + +#if MTK_WCN_HIF_SDIO +static INT32 +mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + INT32 ret = HIF_SDIO_ERR_SUCCESS; + //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n"); + pfWlanRemove(); + + return ret; +} +#else +static void +mtk_sdio_remove ( + struct sdio_func *func + ) +{ + //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n"); + +#if CFG_DBG_GPIO_PINS + //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__); + debug_gpio_deinit(); +#endif + + ASSERT(func); + //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n"); + pfWlanRemove(); + + sdio_claim_host(func); + sdio_disable_func(func); + //printk(KERN_INFO DRV_NAME"sdio_disable_func() done\n"); + sdio_release_host(func); + + //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n"); +} +#endif + +#if (MTK_WCN_HIF_SDIO == 0) +static int +mtk_sdio_suspend ( + struct device * pDev, + pm_message_t state + ) +{ + //printk(KERN_INFO "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev); + //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n"); + + return 0; +} + +int mtk_sdio_resume ( + struct device * pDev + ) +{ + //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev); + + return 0; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +glRegisterBus ( + probe_card pfProbe, + remove_card pfRemove + ) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n"); + //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n"); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + +#if MTK_WCN_HIF_SDIO + /* register MTK sdio client */ + ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE); +#else + mtk_sdio_driver.probe = mtk_sdio_probe; + mtk_sdio_driver.remove = mtk_sdio_remove; + + mtk_sdio_driver.drv.suspend = mtk_sdio_suspend; + mtk_sdio_driver.drv.resume = mtk_sdio_resume; + + ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; +#endif + + return ret; +} /* end of glRegisterBus() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister sdio bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +glUnregisterBus( + remove_card pfRemove + ) +{ + ASSERT(pfRemove); + pfRemove(); + +#if MTK_WCN_HIF_SDIO + /* unregister MTK sdio client */ + mtk_wcn_hif_sdio_client_unreg(&cltInfo); +#else + sdio_unregister_driver(&mtk_sdio_driver); +#endif + + return; +} /* end of glUnregisterBus() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] prGlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +glSetHifInfo ( + P_GLUE_INFO_T prGlueInfo, + UINT_32 u4Cookie + ) +{ + P_GL_HIF_INFO_T prHif = NULL; + + prHif = &prGlueInfo->rHifInfo; + +#if MTK_WCN_HIF_SDIO + //prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie); + prHif->prFuncInfo = prFunc; + prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) u4Cookie); + mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo); + +#else + prHif->func = (struct sdio_func *) u4Cookie; + + //printk(KERN_INFO DRV_NAME"prHif->func->dev = 0x%p\n", &prHif->func->dev); + //printk(KERN_INFO DRV_NAME"prHif->func->vendor = 0x%04X\n", prHif->func->vendor); + //printk(KERN_INFO DRV_NAME"prHif->func->device = 0x%04X\n", prHif->func->device); + //printk(KERN_INFO DRV_NAME"prHif->func->func = 0x%04X\n", prHif->func->num); + + sdio_set_drvdata(prHif->func, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev); +#endif + + return; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +glClearHifInfo ( + P_GLUE_INFO_T prGlueInfo + ) +{ + //P_GL_HIF_INFO_T prHif = NULL; + //ASSERT(prGlueInfo); + //prHif = &prGlueInfo->rHifInfo; + + return; +} /* end of glClearHifInfo() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize bus operation and hif related information, request resources. +* +* \param[out] pvData A pointer to HIF-specific data type buffer. +* For eHPI, pvData is a pointer to UINT_32 type and stores a +* mapped base address. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOL +glBusInit ( + PVOID pvData + ) +{ +#if (MTK_WCN_HIF_SDIO == 0) + int ret = 0; + struct sdio_func *func = NULL; + + ASSERT(pvData); + + func = (struct sdio_func *) pvData; + + sdio_claim_host(func); + ret = sdio_set_block_size(func, 512); + sdio_release_host(func); + + if (ret) { + //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n"); + } + else { + //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n"); + } + + //printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize); + //printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize); + //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size); + //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count); +#endif + return TRUE; +} /* end of glBusInit() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +glBusRelease ( + PVOID pvData + ) +{ + + return; +} /* end of glBusRelease() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +INT_32 +glBusSetIrq ( + PVOID pvData, + PVOID pfnIsr, + PVOID pvCookie + ) +{ + int ret = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + return -1; + } + prNetDevice = (struct net_device *) pvData; + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + return -1; + } + + prHifInfo = &prGlueInfo->rHifInfo; + + sdio_claim_host(prHifInfo->func); + ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt); + sdio_release_host(prHifInfo->func); +#else + /* hif_sdio case */ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + return -1; + } + prNetDevice = (struct net_device *) pvData; + + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + return -1; + } + + mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_TRUE); + +#endif + return ret; +} /* end of glBusSetIrq() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +glBusFreeIrq ( + PVOID pvData, + PVOID pvCookie + ) +{ +#if (MTK_WCN_HIF_SDIO == 0) + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + int ret = 0; + + ASSERT(pvData); + if (!pvData) { + //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__); + return; + } + prNetDevice = (struct net_device *) pvData; + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + + sdio_claim_host(prHifInfo->func); + ret = sdio_release_irq(prHifInfo->func); + sdio_release_host(prHifInfo->func); +#else + /* hif_sdio case */ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__); + return; + } + prNetDevice = (struct net_device *) pvData; + + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__); + return; + } + + mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_FALSE); + +#endif + + return; +} /* end of glBusreeIrq() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register Register offset +* \param[in] pu4Value Pointer to variable used to store read value +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevRegRead ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Register, + OUT PUINT_32 pu4Value + ) +{ + int ret = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value); +#else + if (!in_interrupt) { + sdio_claim_host(prGlueInfo->rHifInfo.func); + } + + *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret); + + if (!in_interrupt) { + sdio_release_host(prGlueInfo->rHifInfo.func); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x", ret); + DBGLOG(HAL, ERROR, ("sdio_readl() reports error: %x", ret)); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register Register offset +* \param[in] u4Value Value to be written +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevRegWrite ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Register, + IN UINT_32 u4Value + ) +{ + int ret = 0; + + ASSERT(prGlueInfo); + +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value); +#else + if (!in_interrupt) { + sdio_claim_host(prGlueInfo->rHifInfo.func); + } + + sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret); + + if (!in_interrupt) { + sdio_release_host(prGlueInfo->rHifInfo.func); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x", ret); + DBGLOG(HAL, ERROR, ("sdio_writel() reports error: %x", ret)); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegWrite() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read device I/O port +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port I/O port offset +* \param[in] u2Len Length to be read +* \param[out] pucBuf Pointer to read buffer +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortRead ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, + IN UINT_16 u2Len, + OUT PUINT_8 pucBuf, + IN UINT_16 u2ValidOutBufSize + ) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucDst = NULL; + int count = u2Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + + #if DBG + //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len); + #endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u2Len <= u2ValidOutBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + ASSERT(prSdioFunc->cur_blksize > 0); + + if (!in_interrupt) { + sdio_claim_host(prSdioFunc); + } + + /* Split buffer into multiple single block to workaround hifsys */ + while (count >= prSdioFunc->cur_blksize) { + count -= prSdioFunc->cur_blksize; + bNum++; + } + if (count > 0 && bNum > 0) { + bNum++; + } + + if (bNum > 0) { + ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum); + +#ifdef CONFIG_X86 + /* ENE workaround */ + { + int tmp; + sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp); + } +#endif + + } + else { + ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count); + } + + if (!in_interrupt) { + sdio_release_host(prSdioFunc); + } +#else + + /* Split buffer into multiple single block to workaround hifsys */ + while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) { + count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz); + bNum++; + } + if (count > 0 && bNum > 0) { + bNum++; + } + + if (bNum > 0) { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } + else { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret); + DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret)); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortRead() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port I/O port offset +* \param[in] u2Len Length to be write +* \param[in] pucBuf Pointer to write buffer +* \param[in] u2ValidInBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortWrite ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, + IN UINT_16 u2Len, + IN PUINT_8 pucBuf, + IN UINT_16 u2ValidInBufSize + ) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucSrc = NULL; + int count = u2Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + + #if DBG + //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len); + #endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT(u2Len <= u2ValidInBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + ASSERT(prSdioFunc->cur_blksize > 0); + + if (!in_interrupt) { + sdio_claim_host(prSdioFunc); + } + + /* Split buffer into multiple single block to workaround hifsys */ + while (count >= prSdioFunc->cur_blksize) { + count -= prSdioFunc->cur_blksize; + bNum++; + } + if (count > 0 && bNum > 0) { + bNum++; + } + + if (bNum > 0) { // block mode + ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum); + +#ifdef CONFIG_X86 + /* ENE workaround */ + { + int tmp; + sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp); + } +#endif + + } + else { // byte mode + + ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count); + } + + if (!in_interrupt) { + sdio_release_host(prSdioFunc); + } +#else + /* Split buffer into multiple single block to workaround hifsys */ + while (count >= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz)) { + count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz); + bNum++; + } + if (count > 0 && bNum > 0) { + bNum++; + } + + if (bNum > 0) { // block mode + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } + else { // byte mode + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %x", ret); + DBGLOG(HAL, ERROR, ("sdio_writesb() reports error: %x", ret)); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port in byte with CMD52 +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Addr I/O port offset +* \param[in] ucData Single byte of data to be written +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevWriteWithSdioCmd52 ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Addr, + IN UINT_8 ucData + ) +{ + int ret = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + if (!in_interrupt) { + sdio_claim_host(prGlueInfo->rHifInfo.func); + } + + sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret); + + if (!in_interrupt) { + sdio_release_host(prGlueInfo->rHifInfo.func); + } +#else + ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData); +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writeb() reports error: %x", ret); + DBGLOG(HAL, ERROR, ("sdio_writeb() reports error: %x", ret)); + } + + return (ret) ? FALSE : TRUE; + +} /* end of kalDevWriteWithSdioCmd52() */ + + +VOID +glSetPowerState ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 ePowerMode + ) +{ + return; +} + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c new file mode 100755 index 000000000000..4322fa303a71 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c @@ -0,0 +1,33 @@ +/****************************************************************************** +*[File] mt6516-evb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* dummy file for build system +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + + +/* +** $Log: mt6516-evb.c $ + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug message + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** +*/ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h new file mode 100755 index 000000000000..9d00b73586a5 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h @@ -0,0 +1,283 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_cfg80211.h#1 $ +*/ + +/*! \file gl_cfg80211.h + \brief This file is for Portable Driver linux cfg80211 support. +*/ + + + +/* +** $Log: gl_cfg80211.h $ +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 29 2012 chinglan.wang +** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng] +** . + * +*/ + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* cfg80211 hooks */ +int +mtk_cfg80211_change_iface ( + struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params + ); + + +int +mtk_cfg80211_add_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + struct key_params *params + ); + + +int +mtk_cfg80211_get_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*) + ); + + +int +mtk_cfg80211_del_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr + ); + + +int +mtk_cfg80211_set_default_key ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool unicast, + bool multicast + ); + + +int +mtk_cfg80211_get_station ( + struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo + ); + + +int +mtk_cfg80211_scan ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_scan_request *request + ); + + +int +mtk_cfg80211_connect ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme + ); + + +int +mtk_cfg80211_disconnect ( + struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code + ); + + +int +mtk_cfg80211_join_ibss ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params + ); + + +int +mtk_cfg80211_leave_ibss ( + struct wiphy *wiphy, + struct net_device *ndev + ); + + +int +mtk_cfg80211_set_power_mgmt ( + struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, + int timeout + ); + + +int +mtk_cfg80211_set_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa + ); + + +int +mtk_cfg80211_del_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa + ); + + +int +mtk_cfg80211_flush_pmksa ( + struct wiphy *wiphy, + struct net_device *ndev + ); + + +int +mtk_cfg80211_remain_on_channel ( + struct wiphy *wiphy, + struct net_device *ndev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, + u64 *cookie + ); + + +int +mtk_cfg80211_cancel_remain_on_channel ( + struct wiphy *wiphy, + struct net_device *ndev, + u64 cookie + ); + + +int +mtk_cfg80211_mgmt_tx ( + struct wiphy *wiphy, + struct net_device *ndev, + struct ieee80211_channel *channel, + bool offscan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie + ); + + +int +mtk_cfg80211_mgmt_tx_cancel_wait ( + struct wiphy *wiphy, + struct net_device *ndev, + u64 cookie + ); + +#if CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); + +int +mtk_cfg80211_testmode_sw_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +#if CFG_SUPPORT_WAPI +int +mtk_cfg80211_testmode_set_key_ext( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +#endif +#else + #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_CFG80211_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h new file mode 100755 index 000000000000..80861bbb5a42 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h @@ -0,0 +1,2250 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_kal.h#1 $ +*/ + +/*! \file gl_kal.h + \brief Declaration of KAL functions - kal*() which is provided by GLUE Layer. + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +/* +** $Log: gl_kal.h $ + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 02 06 2012 wh.su + * [WCXRP00001177] [MT6620 Wi-Fi][Driver][2.2] Adding the query channel filter for AP mode + * adding the channel query filter for AP mode. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adjust the code for Non-DBG and no XLOG. + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters, eCurPsProf, for PS. + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated network type + * include link.h for linux's port. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 01 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface + * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR + * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similiar APIs to hide the difference. + * + * 03 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW table. + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands + * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 12 31 2010 jeffrey.chang + * [WCXRP00000332] [MT6620 Wi-Fi][Driver] add kal sleep function for delay which use blocking call + * modify the implementation of kalDelay to msleep + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not availble then warning message is shown + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at win XP. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 08 02 2010 jeffrey.chang + * NULL + * modify kalSetEvent declaration + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 jeffrey.chang + * + * fix kal header file + * + * 07 22 2010 jeffrey.chang + * + * use different spin lock for security frame + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 19 2010 jeffrey.chang + * + * add new kal api + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * gl_kal merged + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * modify kalMemAlloc method + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when acquiring driver-own, wait for up to 8 seconds. + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL + * * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * * * 2) add KAPI for handling association info + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding firmware download KAPI + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * * * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * * * 2) add 2 kal API for later integration + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download KAPI + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\41 2009-09-28 20:19:23 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\40 2009-08-18 22:57:09 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\39 2009-06-23 23:19:15 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\38 2009-02-09 14:03:17 GMT mtk01090 +** Add KAL function kalDevSetPowerState(). It is not implemented yet. Only add an empty macro. +** +** \main\maintrunk.MT5921\37 2009-01-22 13:05:59 GMT mtk01088 +** new defeine to got 1x value at packet reserved field +** \main\maintrunk.MT5921\36 2008-12-08 16:15:02 GMT mtk01461 +** Add kalQueryValidBufferLength() macro +** \main\maintrunk.MT5921\35 2008-11-13 20:33:15 GMT mtk01104 +** Remove lint warning +** \main\maintrunk.MT5921\34 2008-10-22 11:05:52 GMT mtk01461 +** Remove unused macro +** \main\maintrunk.MT5921\33 2008-10-16 15:48:17 GMT mtk01461 +** Update driver to fix lint warning +** \main\maintrunk.MT5921\32 2008-09-02 11:50:51 GMT mtk01461 +** SPIN_LOCK_SDIO_DDK_TX_QUE +** \main\maintrunk.MT5921\31 2008-08-29 15:58:30 GMT mtk01088 +** remove non-used function for code refine +** \main\maintrunk.MT5921\30 2008-08-21 00:33:29 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\29 2008-06-19 13:29:14 GMT mtk01425 +** 1. Add declaration of SPIN_LOCK_SDIO_DDK_TX_QUE and SPIN_LOCK_SDIO_DDK_RX_QUE +** \main\maintrunk.MT5921\28 2008-05-30 20:27:34 GMT mtk01461 +** Rename KAL function +** \main\maintrunk.MT5921\27 2008-05-30 14:42:05 GMT mtk01461 +** Remove WMM Assoc Flag in KAL +** \main\maintrunk.MT5921\26 2008-05-29 14:15:18 GMT mtk01084 +** remove un-used function +** \main\maintrunk.MT5921\25 2008-04-23 14:02:20 GMT mtk01084 +** modify KAL port access function prototype +** \main\maintrunk.MT5921\24 2008-04-17 23:06:41 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\23 2008-04-08 15:38:50 GMT mtk01084 +** add KAL function to setting pattern search function enable/ disable +** \main\maintrunk.MT5921\22 2008-03-26 15:34:48 GMT mtk01461 +** Add update MAC address func +** \main\maintrunk.MT5921\21 2008-03-18 15:56:15 GMT mtk01084 +** update ENUM_NIC_INITIAL_PARAM_E +** \main\maintrunk.MT5921\20 2008-03-18 11:49:28 GMT mtk01084 +** update function for initial value access +** \main\maintrunk.MT5921\19 2008-03-18 10:21:31 GMT mtk01088 +** use kal update associate request at linux +** \main\maintrunk.MT5921\18 2008-03-14 18:03:41 GMT mtk01084 +** refine register and port access function +** \main\maintrunk.MT5921\17 2008-03-11 14:51:02 GMT mtk01461 +** Add copy_to(from)_user macro +** \main\maintrunk.MT5921\16 2008-03-06 23:42:21 GMT mtk01385 +** 1. add Query Registry Mac address function. +** \main\maintrunk.MT5921\15 2008-02-26 09:48:04 GMT mtk01084 +** modify KAL set network address/ checksum offload part +** \main\maintrunk.MT5921\14 2008-01-09 17:54:58 GMT mtk01084 +** Modify the argument of kalQueryPacketInfo +** \main\maintrunk.MT5921\13 2007-11-29 02:05:20 GMT mtk01461 +** Fix Windows RX multiple packet retain problem +** \main\maintrunk.MT5921\12 2007-11-26 19:43:45 GMT mtk01461 +** Add OS_TIMESTAMP macro +** +** \main\maintrunk.MT5921\11 2007-11-09 16:36:15 GMT mtk01425 +** 1. Modify for CSUM offloading with Tx Fragment +** \main\maintrunk.MT5921\10 2007-11-07 18:38:37 GMT mtk01461 +** Add Tx Fragmentation Support +** \main\maintrunk.MT5921\9 2007-11-06 19:36:50 GMT mtk01088 +** add the WPS related code +** \main\maintrunk.MT5921\8 2007-11-02 01:03:57 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** Revision 1.4 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:50 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:23 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + + +#ifndef _GL_KAL_H +#define _GL_KAL_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "config.h" +#include "gl_typedef.h" +#include "gl_os.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "gl_wext_priv.h" + + +#if CFG_ENABLE_BT_OVER_WIFI + #include "nic/bow.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +//#define USEC_PER_MSEC (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_TX_QUE, + SPIN_LOCK_CMD_QUE, + SPIN_LOCK_TX_RESOURCE, + SPIN_LOCK_CMD_RESOURCE, + SPIN_LOCK_QM_TX_QUEUE, + SPIN_LOCK_CMD_PENDING, + SPIN_LOCK_CMD_SEQ_NUM, + SPIN_LOCK_TX_MSDU_INFO_LIST, + SPIN_LOCK_TXING_MGMT_LIST, + SPIN_LOCK_TX_SEQ_NUM, + SPIN_LOCK_TX_COUNT, + SPIN_LOCK_TXS_COUNT, + /* end */ + SPIN_LOCK_TX, + SPIN_LOCK_IO_REQ, + SPIN_LOCK_INT, + + SPIN_LOCK_MGT_BUF, + SPIN_LOCK_MSG_BUF, + SPIN_LOCK_STA_REC, + + SPIN_LOCK_MAILBOX, + SPIN_LOCK_TIMER, + + SPIN_LOCK_BOW_TABLE, + + SPIN_LOCK_EHPI_BUS, /* only for EHPI */ + SPIN_LOCK_NET_DEV, + SPIN_LOCK_NUM +} ENUM_SPIN_LOCK_CATEGORY_E; + +/* event for assoc infomation update */ +typedef struct _EVENT_ASSOC_INFO { + UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ + UINT_16 u2Length; + PUINT_8 pucIe; +} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; + +typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { + KAL_NETWORK_TYPE_AIS_INDEX = 0, +#if CFG_ENABLE_WIFI_DIRECT + KAL_NETWORK_TYPE_P2P_INDEX, +#endif +#if CFG_ENABLE_BT_OVER_WIFI + KAL_NETWORK_TYPE_BOW_INDEX, +#endif + KAL_NETWORK_TYPE_INDEX_NUM +} ENUM_KAL_NETWORK_TYPE_INDEX_T; + +typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continous */ + MEM_TYPE_NUM +} ENUM_KAL_MEM_ALLOCATION_TYPE; + +#if CONFIG_ANDROID /* Defined in Android kernel source */ +typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#else +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() UINT_32 __u4Flags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__u4Flags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __u4Flags) + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_PKT_QUEUE_ENTRY(_p) GLUE_GET_PKT_QUEUE_ENTRY(_p) +#define KAL_GET_PKT_DESCRIPTOR(_prQueueEntry) GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) +#define KAL_GET_PKT_TID(_p) GLUE_GET_PKT_TID(_p) +#define KAL_GET_PKT_IS1X(_p) GLUE_GET_PKT_IS1X(_p) +#define KAL_GET_PKT_HEADER_LEN(_p) GLUE_GET_PKT_HEADER_LEN(_p) +#define KAL_GET_PKT_PAYLOAD_LEN(_p) GLUE_GET_PKT_PAYLOAD_LEN(_p) +#define KAL_GET_PKT_ARRIVAL_TIME(_p) GLUE_GET_PKT_ARRIVAL_TIME(_p) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CONFIG_ANDROID /* Defined in Android kernel source */ +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + wake_lock_init(_prWakeLock, WAKE_LOCK_SUSPEND, _pcName) + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ + wake_lock_destroy(_prWakeLock) + +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ + wake_lock(_prWakeLock) + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ + wake_lock_timeout(_prWakeLock, _u4Timeout) + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + wake_unlock(_prWakeLock) + +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Cache memory allocation +* +* \param[in] u4Size Required memory size. +* \param[in] eMemType Memory allocation type +* +* \return Pointer to allocated memory +* or NULL +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if(eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + printk(KERN_INFO DRV_NAME "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __FUNCTION__); \ + } \ + pvAddr; \ + }) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if(eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + pvAddr; \ + }) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free allocated cache memory +* +* \param[in] pvAddr Required memory size. +* \param[in] eMemType Memory allocation type +* \param[in] u4Size Allocated memory size. +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ + { \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + printk(KERN_INFO DRV_NAME "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __FUNCTION__); \ + } \ + if(eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ + } +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ + { \ + if(eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ + } +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) + +/* Copy memory from user space to kernel space */ +#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) copy_from_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory from kernel space to user space */ +#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) copy_to_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory block with specific size */ +#define kalMemCopy(pvDst, pvSrc, u4Size) memcpy(pvDst, pvSrc, u4Size) + +/* Set memory block with specific pattern */ +#define kalMemSet(pvAddr, ucPattern, u4Size) memset(pvAddr, ucPattern, u4Size) + +/* Compare two memory block with specific length. + * Return zero if they are the same. + */ +#define kalMemCmp(pvAddr1, pvAddr2, u4Size) memcmp(pvAddr1, pvAddr2, u4Size) + +/* Zero specific memory block */ +#define kalMemZero(pvAddr, u4Size) memset(pvAddr, 0, u4Size) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalSendComplete(prGlueInfo, pvPacket, status) \ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to locate the starting address of incoming ethernet +* frame for skb. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ + ((PUINT_8)((struct sk_buff *)pvPacket)->data) + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to query the length of valid buffer which is accessible during +* port read/write. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ + ((UINT_32)((struct sk_buff *)pvPacket)->end - \ + (UINT_32)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to copy the entire frame from skb to the destination +* address in the input parameter. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] pucDestBuffer Destination Address +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len);} + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define kalPrint printk + +#if !DBG +#if CFG_SUPPORT_XLOG +#define XLOG_TAG "wlan" + +#define XLOG_FUNC(__LEVEL, __FMT...)\ + if (__LEVEL == ANDROID_LOG_ERROR) {\ + xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, ##__FMT);\ + } \ + else if (__LEVEL == ANDROID_LOG_WARN) {\ + xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, ##__FMT);\ + } \ + else if (__LEVEL == ANDROID_LOG_INFO) {\ + xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, ##__FMT);\ + } \ + else if (__LEVEL == ANDROID_LOG_DEBUG) {\ + xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, ##__FMT);\ + } \ + else if (__LEVEL == ANDROID_LOG_VERBOSE) {\ + xlog_printk(ANDROID_LOG_VERBOSE, XLOG_TAG, ##__FMT);\ + } + +#define AIS_ERROR_LOGFUNC(_Fmt...) +#define AIS_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define AIS_INFO_LOGFUNC(_Fmt...) +#define AIS_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define AIS_EVENT_LOGFUNC(_Fmt...) +#define AIS_TRACE_LOGFUNC(_Fmt...) +#define AIS_LOUD_LOGFUNC(_Fmt...) +#define AIS_TEMP_LOGFUNC(_Fmt...) + +#define AIS_ERROR_LOGDUMP8(x, y) +#define AIS_WARN_LOGDUMP8(x, y) +#define AIS_INFO_LOGDUMP8(x, y) +#define AIS_STATE_LOGDUMP8(x, y) +#define AIS_EVENT_LOGDUMP8(x, y) +#define AIS_TRACE_LOGDUMP8(x, y) +#define AIS_LOUD_LOGDUMP8(x, y) +#define AIS_TEMP_LOGDUMP8(x, y) + +#define INTR_ERROR_LOGFUNC(_Fmt...) +#define INTR_WARN_LOGFUNC(_Fmt...) +#define INTR_INFO_LOGFUNC(_Fmt...) +#define INTR_STATE_LOGFUNC(_Fmt...) +#define INTR_EVENT_LOGFUNC(_Fmt...) +#define INTR_TRACE_LOGFUNC(_Fmt...) +#define INTR_LOUD_LOGFUNC(_Fmt...) +#define INTR_TEMP_LOGFUNC(_Fmt...) + +#define INTR_ERROR_LOGDUMP8(x, y) +#define INTR_WARN_LOGDUMP8(x, y) +#define INTR_INFO_LOGDUMP8(x, y) +#define INTR_STATE_LOGDUMP8(x, y) +#define INTR_EVENT_LOGDUMP8(x, y) +#define INTR_TRACE_LOGDUMP8(x, y) +#define INTR_LOUD_LOGDUMP8(x, y) +#define INTR_TEMP_LOGDUMP8(x, y) + +#define INIT_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define INIT_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define INIT_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define INIT_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define INIT_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define INIT_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt) +#define INIT_LOUD_LOGFUNC(_Fmt...) +#define INIT_TEMP_LOGFUNC(_Fmt...) + +#define INIT_ERROR_LOGDUMP8(x, y) +#define INIT_WARN_LOGDUMP8(x, y) +#define INIT_INFO_LOGDUMP8(x, y) +#define INIT_STATE_LOGDUMP8(x, y) +#define INIT_EVENT_LOGDUMP8(x, y) +#define INIT_TRACE_LOGDUMP8(x, y) +#define INIT_LOUD_LOGDUMP8(x, y) +#define INIT_TEMP_LOGDUMP8(x, y) + +#define AAA_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define AAA_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define AAA_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define AAA_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define AAA_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define AAA_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt) +#define AAA_LOUD_LOGFUNC(_Fmt...) +#define AAA_TEMP_LOGFUNC(_Fmt...) + +#define AAA_ERROR_LOGDUMP8(x, y) +#define AAA_WARN_LOGDUMP8(x, y) +#define AAA_INFO_LOGDUMP8(x, y) +#define AAA_STATE_LOGDUMP8(x, y) +#define AAA_EVENT_LOGDUMP8(x, y) +#define AAA_TRACE_LOGDUMP8(x, y) +#define AAA_LOUD_LOGDUMP8(x, y) +#define AAA_TEMP_LOGDUMP8(x, y) + +#define ROAMING_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define ROAMING_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define ROAMING_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define ROAMING_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define ROAMING_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define ROAMING_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt) +#define ROAMING_LOUD_LOGFUNC(_Fmt...) +#define ROAMING_TEMP_LOGFUNC(_Fmt...) + +#define ROAMING_ERROR_LOGDUMP8(x, y) +#define ROAMING_WARN_LOGDUMP8(x, y) +#define ROAMING_INFO_LOGDUMP8(x, y) +#define ROAMING_STATE_LOGDUMP8(x, y) +#define ROAMING_EVENT_LOGDUMP8(x, y) +#define ROAMING_TRACE_LOGDUMP8(x, y) +#define ROAMING_LOUD_LOGDUMP8(x, y) +#define ROAMING_TEMP_LOGDUMP8(x, y) + +#define REQ_ERROR_LOGFUNC(_Fmt...) +#define REQ_WARN_LOGFUNC(_Fmt...) +#define REQ_INFO_LOGFUNC(_Fmt...) +#define REQ_STATE_LOGFUNC(_Fmt...) +#define REQ_EVENT_LOGFUNC(_Fmt...) +#define REQ_TRACE_LOGFUNC(_Fmt...) +#define REQ_LOUD_LOGFUNC(_Fmt...) +#define REQ_TEMP_LOGFUNC(_Fmt...) + +#define REQ_ERROR_LOGDUMP8(x, y) +#define REQ_WARN_LOGDUMP8(x, y) +#define REQ_INFO_LOGDUMP8(x, y) +#define REQ_STATE_LOGDUMP8(x, y) +#define REQ_EVENT_LOGDUMP8(x, y) +#define REQ_TRACE_LOGDUMP8(x, y) +#define REQ_LOUD_LOGDUMP8(x, y) +#define REQ_TEMP_LOGDUMP8(x, y) + +#define TX_ERROR_LOGFUNC(_Fmt...) +#define TX_WARN_LOGFUNC(_Fmt...) +#define TX_INFO_LOGFUNC(_Fmt...) +#define TX_STATE_LOGFUNC(_Fmt...) +#define TX_EVENT_LOGFUNC(_Fmt...) +#define TX_TRACE_LOGFUNC(_Fmt...) +#define TX_LOUD_LOGFUNC(_Fmt...) +#define TX_TEMP_LOGFUNC(_Fmt...) + +#define TX_ERROR_LOGDUMP8(x, y) +#define TX_WARN_LOGDUMP8(x, y) +#define TX_INFO_LOGDUMP8(x, y) +#define TX_STATE_LOGDUMP8(x, y) +#define TX_EVENT_LOGDUMP8(x, y) +#define TX_TRACE_LOGDUMP8(x, y) +#define TX_LOUD_LOGDUMP8(x, y) +#define TX_TEMP_LOGDUMP8(x, y) + +#define RX_ERROR_LOGFUNC(_Fmt...) +#define RX_WARN_LOGFUNC(_Fmt...) +#define RX_INFO_LOGFUNC(_Fmt...) +#define RX_STATE_LOGFUNC(_Fmt...) +#define RX_EVENT_LOGFUNC(_Fmt...) +#define RX_TRACE_LOGFUNC(_Fmt...) +#define RX_LOUD_LOGFUNC(_Fmt...) +#define RX_TEMP_LOGFUNC(_Fmt...) + +#define RX_ERROR_LOGDUMP8(x, y) +#define RX_WARN_LOGDUMP8(x, y) +#define RX_INFO_LOGDUMP8(x, y) +#define RX_STATE_LOGDUMP8(x, y) +#define RX_EVENT_LOGDUMP8(x, y) +#define RX_TRACE_LOGDUMP8(x, y) +#define RX_LOUD_LOGDUMP8(x, y) +#define RX_TEMP_LOGDUMP8(x, y) + +#define RFTEST_ERROR_LOGFUNC(_Fmt...) +#define RFTEST_WARN_LOGFUNC(_Fmt...) +#define RFTEST_INFO_LOGFUNC(_Fmt...) +#define RFTEST_STATE_LOGFUNC(_Fmt...) +#define RFTEST_EVENT_LOGFUNC(_Fmt...) +#define RFTEST_TRACE_LOGFUNC(_Fmt...) +#define RFTEST_LOUD_LOGFUNC(_Fmt...) +#define RFTEST_TEMP_LOGFUNC(_Fmt...) + +#define RFTEST_ERROR_LOGDUMP8(x, y) +#define RFTEST_WARN_LOGDUMP8(x, y) +#define RFTEST_INFO_LOGDUMP8(x, y) +#define RFTEST_STATE_LOGDUMP8(x, y) +#define RFTEST_EVENT_LOGDUMP8(x, y) +#define RFTEST_TRACE_LOGDUMP8(x, y) +#define RFTEST_LOUD_LOGDUMP8(x, y) +#define RFTEST_TEMP_LOGDUMP8(x, y) + +#define EMU_ERROR_LOGFUNC(_Fmt...) +#define EMU_WARN_LOGFUNC(_Fmt...) +#define EMU_INFO_LOGFUNC(_Fmt...) +#define EMU_STATE_LOGFUNC(_Fmt...) +#define EMU_EVENT_LOGFUNC(_Fmt...) +#define EMU_TRACE_LOGFUNC(_Fmt...) +#define EMU_LOUD_LOGFUNC(_Fmt...) +#define EMU_TEMP_LOGFUNC(_Fmt...) + +#define EMU_ERROR_LOGDUMP8(x, y) +#define EMU_WARN_LOGDUMP8(x, y) +#define EMU_INFO_LOGDUMP8(x, y) +#define EMU_STATE_LOGDUMP8(x, y) +#define EMU_EVENT_LOGDUMP8(x, y) +#define EMU_TRACE_LOGDUMP8(x, y) +#define EMU_LOUD_LOGDUMP8(x, y) +#define EMU_TEMP_LOGDUMP8(x, y) + +#define HEM_ERROR_LOGFUNC(_Fmt...) +#define HEM_WARN_LOGFUNC(_Fmt...) +#define HEM_INFO_LOGFUNC(_Fmt...) +#define HEM_STATE_LOGFUNC(_Fmt...) +#define HEM_EVENT_LOGFUNC(_Fmt...) +#define HEM_TRACE_LOGFUNC(_Fmt...) +#define HEM_LOUD_LOGFUNC(_Fmt...) +#define HEM_TEMP_LOGFUNC(_Fmt...) + +#define HEM_ERROR_LOGDUMP8(x, y) +#define HEM_WARN_LOGDUMP8(x, y) +#define HEM_INFO_LOGDUMP8(x, y) +#define HEM_STATE_LOGDUMP8(x, y) +#define HEM_EVENT_LOGDUMP8(x, y) +#define HEM_TRACE_LOGDUMP8(x, y) +#define HEM_LOUD_LOGDUMP8(x, y) +#define HEM_TEMP_LOGDUMP8(x, y) + +#define RLM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define RLM_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define RLM_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define RLM_STATE_LOGFUNC(_Fmt...) +#define RLM_EVENT_LOGFUNC(_Fmt...) +#define RLM_TRACE_LOGFUNC(_Fmt...) +#define RLM_LOUD_LOGFUNC(_Fmt...) +#define RLM_TEMP_LOGFUNC(_Fmt...) + +#define RLM_ERROR_LOGDUMP8(x, y) +#define RLM_WARN_LOGDUMP8(x, y) +#define RLM_INFO_LOGDUMP8(x, y) +#define RLM_STATE_LOGDUMP8(x, y) +#define RLM_EVENT_LOGDUMP8(x, y) +#define RLM_TRACE_LOGDUMP8(x, y) +#define RLM_LOUD_LOGDUMP8(x, y) +#define RLM_TEMP_LOGDUMP8(x, y) + +#define MEM_ERROR_LOGFUNC(_Fmt...) +#define MEM_WARN_LOGFUNC(_Fmt...) +#define MEM_INFO_LOGFUNC(_Fmt...) +#define MEM_STATE_LOGFUNC(_Fmt...) +#define MEM_EVENT_LOGFUNC(_Fmt...) +#define MEM_TRACE_LOGFUNC(_Fmt...) +#define MEM_LOUD_LOGFUNC(_Fmt...) +#define MEM_TEMP_LOGFUNC(_Fmt...) + +#define MEM_ERROR_LOGDUMP8(x, y) +#define MEM_WARN_LOGDUMP8(x, y) +#define MEM_INFO_LOGDUMP8(x, y) +#define MEM_STATE_LOGDUMP8(x, y) +#define MEM_EVENT_LOGDUMP8(x, y) +#define MEM_TRACE_LOGDUMP8(x, y) +#define MEM_LOUD_LOGDUMP8(x, y) +#define MEM_TEMP_LOGDUMP8(x, y) + +#define CNM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define CNM_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define CNM_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define CNM_STATE_LOGFUNC(_Fmt...) +#define CNM_EVENT_LOGFUNC(_Fmt...) +#define CNM_TRACE_LOGFUNC(_Fmt...) +#define CNM_LOUD_LOGFUNC(_Fmt...) +#define CNM_TEMP_LOGFUNC(_Fmt...) + +#define CNM_ERROR_LOGDUMP8(x, y) +#define CNM_WARN_LOGDUMP8(x, y) +#define CNM_INFO_LOGDUMP8(x, y) +#define CNM_STATE_LOGDUMP8(x, y) +#define CNM_EVENT_LOGDUMP8(x, y) +#define CNM_TRACE_LOGDUMP8(x, y) +#define CNM_LOUD_LOGDUMP8(x, y) +#define CNM_TEMP_LOGDUMP8(x, y) + +#define RSN_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define RSN_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define RSN_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define RSN_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define RSN_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define RSN_TRACE_LOGFUNC(_Fmt...) +#define RSN_LOUD_LOGFUNC(_Fmt...) +#define RSN_TEMP_LOGFUNC(_Fmt...) + +#define RSN_ERROR_LOGDUMP8(x, y) +#define RSN_WARN_LOGDUMP8(x, y) +#define RSN_INFO_LOGDUMP8(x, y) +#define RSN_STATE_LOGDUMP8(x, y) +#define RSN_EVENT_LOGDUMP8(x, y) +#define RSN_TRACE_LOGDUMP8(x, y) +#define RSN_LOUD_LOGDUMP8(x, y) +#define RSN_TEMP_LOGDUMP8(x, y) + +#define BSS_ERROR_LOGFUNC(_Fmt...) +#define BSS_WARN_LOGFUNC(_Fmt...) +#define BSS_INFO_LOGFUNC(_Fmt...) +#define BSS_STATE_LOGFUNC(_Fmt...) +#define BSS_EVENT_LOGFUNC(_Fmt...) +#define BSS_TRACE_LOGFUNC(_Fmt...) +#define BSS_LOUD_LOGFUNC(_Fmt...) +#define BSS_TEMP_LOGFUNC(_Fmt...) + +#define BSS_ERROR_LOGDUMP8(x, y) +#define BSS_WARN_LOGDUMP8(x, y) +#define BSS_INFO_LOGDUMP8(x, y) +#define BSS_STATE_LOGDUMP8(x, y) +#define BSS_EVENT_LOGDUMP8(x, y) +#define BSS_TRACE_LOGDUMP8(x, y) +#define BSS_LOUD_LOGDUMP8(x, y) +#define BSS_TEMP_LOGDUMP8(x, y) + +#define SCN_ERROR_LOGFUNC(_Fmt...) +#define SCN_WARN_LOGFUNC(_Fmt...) +#define SCN_INFO_LOGFUNC(_Fmt...) +#define SCN_STATE_LOGFUNC(_Fmt...) +#define SCN_EVENT_LOGFUNC(_Fmt...) +#define SCN_TRACE_LOGFUNC(_Fmt...) +#define SCN_LOUD_LOGFUNC(_Fmt...) +#define SCN_TEMP_LOGFUNC(_Fmt...) + +#define SCN_ERROR_LOGDUMP8(x, y) +#define SCN_WARN_LOGDUMP8(x, y) +#define SCN_INFO_LOGDUMP8(x, y) +#define SCN_STATE_LOGDUMP8(x, y) +#define SCN_EVENT_LOGDUMP8(x, y) +#define SCN_TRACE_LOGDUMP8(x, y) +#define SCN_LOUD_LOGDUMP8(x, y) +#define SCN_TEMP_LOGDUMP8(x, y) + +#define SAA_ERROR_LOGFUNC(_Fmt...) +#define SAA_WARN_LOGFUNC(_Fmt...) +#define SAA_INFO_LOGFUNC(_Fmt...) +#define SAA_STATE_LOGFUNC(_Fmt...) +#define SAA_EVENT_LOGFUNC(_Fmt...) +#define SAA_TRACE_LOGFUNC(_Fmt...) +#define SAA_LOUD_LOGFUNC(_Fmt...) +#define SAA_TEMP_LOGFUNC(_Fmt...) + +#define SAA_ERROR_LOGDUMP8(x, y) +#define SAA_WARN_LOGDUMP8(x, y) +#define SAA_INFO_LOGDUMP8(x, y) +#define SAA_STATE_LOGDUMP8(x, y) +#define SAA_EVENT_LOGDUMP8(x, y) +#define SAA_TRACE_LOGDUMP8(x, y) +#define SAA_LOUD_LOGDUMP8(x, y) +#define SAA_TEMP_LOGDUMP8(x, y) + +#define P2P_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define P2P_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define P2P_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define P2P_STATE_LOGFUNC(_Fmt...) +#define P2P_EVENT_LOGFUNC(_Fmt...) +#define P2P_TRACE_LOGFUNC(_Fmt...) +#define P2P_LOUD_LOGFUNC(_Fmt...) +#define P2P_TEMP_LOGFUNC(_Fmt...) + +#define P2P_ERROR_LOGDUMP8(x, y) +#define P2P_WARN_LOGDUMP8(x, y) +#define P2P_INFO_LOGDUMP8(x, y) +#define P2P_STATE_LOGDUMP8(x, y) +#define P2P_EVENT_LOGDUMP8(x, y) +#define P2P_TRACE_LOGDUMP8(x, y) +#define P2P_LOUD_LOGDUMP8(x, y) +#define P2P_TEMP_LOGDUMP8(x, y) + +#define QM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define QM_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) +#define QM_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define QM_STATE_LOGFUNC(_Fmt...) +#define QM_EVENT_LOGFUNC(_Fmt...) +#define QM_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt) +#define QM_LOUD_LOGFUNC(_Fmt...) +#define QM_TEMP_LOGFUNC(_Fmt...) + +#define QM_ERROR_LOGDUMP8(x, y) +#define QM_WARN_LOGDUMP8(x, y) +#define QM_INFO_LOGDUMP8(x, y) +#define QM_STATE_LOGDUMP8(x, y) +#define QM_EVENT_LOGDUMP8(x, y) +#define QM_TRACE_LOGDUMP8(x, y) +#define QM_LOUD_LOGDUMP8(x, y) +#define QM_TEMP_LOGDUMP8(x, y) + +#define SEC_ERROR_LOGFUNC(_Fmt...) +#define SEC_WARN_LOGFUNC(_Fmt...) +#define SEC_INFO_LOGFUNC(_Fmt...) +#define SEC_STATE_LOGFUNC(_Fmt...) +#define SEC_EVENT_LOGFUNC(_Fmt...) +#define SEC_TRACE_LOGFUNC(_Fmt...) +#define SEC_LOUD_LOGFUNC(_Fmt...) +#define SEC_TEMP_LOGFUNC(_Fmt...) + +#define SEC_ERROR_LOGDUMP8(x, y) +#define SEC_WARN_LOGDUMP8(x, y) +#define SEC_INFO_LOGDUMP8(x, y) +#define SEC_STATE_LOGDUMP8(x, y) +#define SEC_EVENT_LOGDUMP8(x, y) +#define SEC_TRACE_LOGDUMP8(x, y) +#define SEC_LOUD_LOGDUMP8(x, y) +#define SEC_TEMP_LOGDUMP8(x, y) + +#define BOW_ERROR_LOGFUNC(_Fmt...) +#define BOW_WARN_LOGFUNC(_Fmt...) +#define BOW_INFO_LOGFUNC(_Fmt...) +#define BOW_STATE_LOGFUNC(_Fmt...) +#define BOW_EVENT_LOGFUNC(_Fmt...) +#define BOW_TRACE_LOGFUNC(_Fmt...) +#define BOW_LOUD_LOGFUNC(_Fmt...) +#define BOW_TEMP_LOGFUNC(_Fmt...) + +#define BOW_ERROR_LOGDUMP8(x, y) +#define BOW_WARN_LOGDUMP8(x, y) +#define BOW_INFO_LOGDUMP8(x, y) +#define BOW_STATE_LOGDUMP8(x, y) +#define BOW_EVENT_LOGDUMP8(x, y) +#define BOW_TRACE_LOGDUMP8(x, y) +#define BOW_LOUD_LOGDUMP8(x, y) +#define BOW_TEMP_LOGDUMP8(x, y) + +#define HAL_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) +#define HAL_WARN_LOGFUNC(_Fmt...) +#define HAL_INFO_LOGFUNC(_Fmt...) +#define HAL_STATE_LOGFUNC(_Fmt...) +#define HAL_EVENT_LOGFUNC(_Fmt...) +#define HAL_TRACE_LOGFUNC(_Fmt...) +#define HAL_LOUD_LOGFUNC(_Fmt...) +#define HAL_TEMP_LOGFUNC(_Fmt...) + +#define HAL_ERROR_LOGDUMP8(x, y) +#define HAL_WARN_LOGDUMP8(x, y) +#define HAL_INFO_LOGDUMP8(x, y) +#define HAL_STATE_LOGDUMP8(x, y) +#define HAL_EVENT_LOGDUMP8(x, y) +#define HAL_TRACE_LOGDUMP8(x, y) +#define HAL_LOUD_LOGDUMP8(x, y) +#define HAL_TEMP_LOGDUMP8(x, y) + +#define WAPI_ERROR_LOGFUNC(_Fmt...) +#define WAPI_WARN_LOGFUNC(_Fmt...) +#define WAPI_INFO_LOGFUNC(_Fmt...) +#define WAPI_STATE_LOGFUNC(_Fmt...) +#define WAPI_EVENT_LOGFUNC(_Fmt...) +#define WAPI_TRACE_LOGFUNC(_Fmt...) +#define WAPI_LOUD_LOGFUNC(_Fmt...) +#define WAPI_TEMP_LOGFUNC(_Fmt...) + +#define WAPI_ERROR_LOGDUMP8(x, y) +#define WAPI_WARN_LOGDUMP8(x, y) +#define WAPI_INFO_LOGDUMP8(x, y) +#define WAPI_STATE_LOGDUMP8(x, y) +#define WAPI_EVENT_LOGDUMP8(x, y) +#define WAPI_TRACE_LOGDUMP8(x, y) +#define WAPI_LOUD_LOGDUMP8(x, y) +#define WAPI_TEMP_LOGDUMP8(x, y) + +#define SW1_ERROR_LOGFUNC(_Fmt...) +#define SW1_WARN_LOGFUNC(_Fmt...) +#define SW1_INFO_LOGFUNC(_Fmt...) +#define SW1_STATE_LOGFUNC(_Fmt...) +#define SW1_EVENT_LOGFUNC(_Fmt...) +#define SW1_TRACE_LOGFUNC(_Fmt...) +#define SW1_LOUD_LOGFUNC(_Fmt...) +#define SW1_TEMP_LOGFUNC(_Fmt...) + +#define SW1_ERROR_LOGDUMP8(x, y) +#define SW1_WARN_LOGDUMP8(x, y) +#define SW1_INFO_LOGDUMP8(x, y) +#define SW1_STATE_LOGDUMP8(x, y) +#define SW1_EVENT_LOGDUMP8(x, y) +#define SW1_TRACE_LOGDUMP8(x, y) +#define SW1_LOUD_LOGDUMP8(x, y) +#define SW1_TEMP_LOGDUMP8(x, y) + +#define SW2_ERROR_LOGFUNC(_Fmt...) +#define SW2_WARN_LOGFUNC(_Fmt...) +#define SW2_INFO_LOGFUNC(_Fmt...) +#define SW2_STATE_LOGFUNC(_Fmt...) +#define SW2_EVENT_LOGFUNC(_Fmt...) +#define SW2_TRACE_LOGFUNC(_Fmt...) +#define SW2_LOUD_LOGFUNC(_Fmt...) +#define SW2_TEMP_LOGFUNC(_Fmt...) + +#define SW2_ERROR_LOGDUMP8(x, y) +#define SW2_WARN_LOGDUMP8(x, y) +#define SW2_INFO_LOGDUMP8(x, y) +#define SW2_STATE_LOGDUMP8(x, y) +#define SW2_EVENT_LOGDUMP8(x, y) +#define SW2_TRACE_LOGDUMP8(x, y) +#define SW2_LOUD_LOGDUMP8(x, y) +#define SW2_TEMP_LOGDUMP8(x, y) + +#define SW3_ERROR_LOGFUNC(_Fmt...) +#define SW3_WARN_LOGFUNC(_Fmt...) +#define SW3_INFO_LOGFUNC(_Fmt...) +#define SW3_STATE_LOGFUNC(_Fmt...) +#define SW3_EVENT_LOGFUNC(_Fmt...) +#define SW3_TRACE_LOGFUNC(_Fmt...) +#define SW3_LOUD_LOGFUNC(_Fmt...) +#define SW3_TEMP_LOGFUNC(_Fmt...) + +#define SW3_ERROR_LOGDUMP8(x, y) +#define SW3_WARN_LOGDUMP8(x, y) +#define SW3_INFO_LOGDUMP8(x, y) +#define SW3_STATE_LOGDUMP8(x, y) +#define SW3_EVENT_LOGDUMP8(x, y) +#define SW3_TRACE_LOGDUMP8(x, y) +#define SW3_LOUD_LOGDUMP8(x, y) +#define SW3_TEMP_LOGDUMP8(x, y) + +#define SW4_ERROR_LOGFUNC(_Fmt...) +#define SW4_WARN_LOGFUNC(_Fmt...) +#define SW4_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt) +#define SW4_STATE_LOGFUNC(_Fmt...) +#define SW4_EVENT_LOGFUNC(_Fmt...) +#define SW4_TRACE_LOGFUNC(_Fmt...) +#define SW4_LOUD_LOGFUNC(_Fmt...) +#define SW4_TEMP_LOGFUNC(_Fmt...) + +#define SW4_ERROR_LOGDUMP8(x, y) +#define SW4_WARN_LOGDUMP8(x, y) +#define SW4_INFO_LOGDUMP8(x, y) +#define SW4_STATE_LOGDUMP8(x, y) +#define SW4_EVENT_LOGDUMP8(x, y) +#define SW4_TRACE_LOGDUMP8(x, y) dumpMemory8(ANDROID_LOG_DEBUG, x, y) +#define SW4_LOUD_LOGDUMP8(x, y) +#define SW4_TEMP_LOGDUMP8(x, y) +#else +#define AIS_ERROR_LOGFUNC(_Fmt...) +#define AIS_WARN_LOGFUNC(_Fmt...) +#define AIS_INFO_LOGFUNC(_Fmt...) +#define AIS_STATE_LOGFUNC(_Fmt...) +#define AIS_EVENT_LOGFUNC(_Fmt...) +#define AIS_TRACE_LOGFUNC(_Fmt...) +#define AIS_LOUD_LOGFUNC(_Fmt...) +#define AIS_TEMP_LOGFUNC(_Fmt...) + +#define INTR_ERROR_LOGFUNC(_Fmt...) +#define INTR_WARN_LOGFUNC(_Fmt...) +#define INTR_INFO_LOGFUNC(_Fmt...) +#define INTR_STATE_LOGFUNC(_Fmt...) +#define INTR_EVENT_LOGFUNC(_Fmt...) +#define INTR_TRACE_LOGFUNC(_Fmt...) +#define INTR_LOUD_LOGFUNC(_Fmt...) +#define INTR_TEMP_LOGFUNC(_Fmt...) + +#define INIT_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_TRACE_LOGFUNC(_Fmt...) +#define INIT_LOUD_LOGFUNC(_Fmt...) +#define INIT_TEMP_LOGFUNC(_Fmt...) + +#define AAA_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_LOUD_LOGFUNC(_Fmt...) +#define AAA_TEMP_LOGFUNC(_Fmt...) + +#define ROAMING_ERROR_LOGFUNC(_Fmt...) +#define ROAMING_WARN_LOGFUNC(_Fmt...) +#define ROAMING_INFO_LOGFUNC(_Fmt...) +#define ROAMING_STATE_LOGFUNC(_Fmt...) +#define ROAMING_EVENT_LOGFUNC(_Fmt...) +#define ROAMING_TRACE_LOGFUNC(_Fmt...) +#define ROAMING_LOUD_LOGFUNC(_Fmt...) +#define ROAMING_TEMP_LOGFUNC(_Fmt...) + +#define REQ_ERROR_LOGFUNC(_Fmt...) +#define REQ_WARN_LOGFUNC(_Fmt...) +#define REQ_INFO_LOGFUNC(_Fmt...) +#define REQ_STATE_LOGFUNC(_Fmt...) +#define REQ_EVENT_LOGFUNC(_Fmt...) +#define REQ_TRACE_LOGFUNC(_Fmt...) +#define REQ_LOUD_LOGFUNC(_Fmt...) +#define REQ_TEMP_LOGFUNC(_Fmt...) + +#define TX_ERROR_LOGFUNC(_Fmt...) +#define TX_WARN_LOGFUNC(_Fmt...) +#define TX_INFO_LOGFUNC(_Fmt...) +#define TX_STATE_LOGFUNC(_Fmt...) +#define TX_EVENT_LOGFUNC(_Fmt...) +#define TX_TRACE_LOGFUNC(_Fmt...) +#define TX_LOUD_LOGFUNC(_Fmt...) +#define TX_TEMP_LOGFUNC(_Fmt...) + +#define RX_ERROR_LOGFUNC(_Fmt...) +#define RX_WARN_LOGFUNC(_Fmt...) +#define RX_INFO_LOGFUNC(_Fmt...) +#define RX_STATE_LOGFUNC(_Fmt...) +#define RX_EVENT_LOGFUNC(_Fmt...) +#define RX_TRACE_LOGFUNC(_Fmt...) +#define RX_LOUD_LOGFUNC(_Fmt...) +#define RX_TEMP_LOGFUNC(_Fmt...) + +#define RFTEST_ERROR_LOGFUNC(_Fmt...) +#define RFTEST_WARN_LOGFUNC(_Fmt...) +#define RFTEST_INFO_LOGFUNC(_Fmt...) +#define RFTEST_STATE_LOGFUNC(_Fmt...) +#define RFTEST_EVENT_LOGFUNC(_Fmt...) +#define RFTEST_TRACE_LOGFUNC(_Fmt...) +#define RFTEST_LOUD_LOGFUNC(_Fmt...) +#define RFTEST_TEMP_LOGFUNC(_Fmt...) + +#define EMU_ERROR_LOGFUNC(_Fmt...) +#define EMU_WARN_LOGFUNC(_Fmt...) +#define EMU_INFO_LOGFUNC(_Fmt...) +#define EMU_STATE_LOGFUNC(_Fmt...) +#define EMU_EVENT_LOGFUNC(_Fmt...) +#define EMU_TRACE_LOGFUNC(_Fmt...) +#define EMU_LOUD_LOGFUNC(_Fmt...) +#define EMU_TEMP_LOGFUNC(_Fmt...) + +#define HEM_ERROR_LOGFUNC(_Fmt...) +#define HEM_WARN_LOGFUNC(_Fmt...) +#define HEM_INFO_LOGFUNC(_Fmt...) +#define HEM_STATE_LOGFUNC(_Fmt...) +#define HEM_EVENT_LOGFUNC(_Fmt...) +#define HEM_TRACE_LOGFUNC(_Fmt...) +#define HEM_LOUD_LOGFUNC(_Fmt...) +#define HEM_TEMP_LOGFUNC(_Fmt...) + +#define RLM_ERROR_LOGFUNC(_Fmt...) +#define RLM_WARN_LOGFUNC(_Fmt...) +#define RLM_INFO_LOGFUNC(_Fmt...) +#define RLM_STATE_LOGFUNC(_Fmt...) +#define RLM_EVENT_LOGFUNC(_Fmt...) +#define RLM_TRACE_LOGFUNC(_Fmt...) +#define RLM_LOUD_LOGFUNC(_Fmt...) +#define RLM_TEMP_LOGFUNC(_Fmt...) + +#define MEM_ERROR_LOGFUNC(_Fmt...) +#define MEM_WARN_LOGFUNC(_Fmt...) +#define MEM_INFO_LOGFUNC(_Fmt...) +#define MEM_STATE_LOGFUNC(_Fmt...) +#define MEM_EVENT_LOGFUNC(_Fmt...) +#define MEM_TRACE_LOGFUNC(_Fmt...) +#define MEM_LOUD_LOGFUNC(_Fmt...) +#define MEM_TEMP_LOGFUNC(_Fmt...) + +#define CNM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_STATE_LOGFUNC(_Fmt...) +#define CNM_EVENT_LOGFUNC(_Fmt...) +#define CNM_TRACE_LOGFUNC(_Fmt...) +#define CNM_LOUD_LOGFUNC(_Fmt...) +#define CNM_TEMP_LOGFUNC(_Fmt...) + +#define RSN_ERROR_LOGFUNC(_Fmt...) +#define RSN_WARN_LOGFUNC(_Fmt...) +#define RSN_INFO_LOGFUNC(_Fmt...) +#define RSN_STATE_LOGFUNC(_Fmt...) +#define RSN_EVENT_LOGFUNC(_Fmt...) +#define RSN_TRACE_LOGFUNC(_Fmt...) +#define RSN_LOUD_LOGFUNC(_Fmt...) +#define RSN_TEMP_LOGFUNC(_Fmt...) + +#define BSS_ERROR_LOGFUNC(_Fmt...) +#define BSS_WARN_LOGFUNC(_Fmt...) +#define BSS_INFO_LOGFUNC(_Fmt...) +#define BSS_STATE_LOGFUNC(_Fmt...) +#define BSS_EVENT_LOGFUNC(_Fmt...) +#define BSS_TRACE_LOGFUNC(_Fmt...) +#define BSS_LOUD_LOGFUNC(_Fmt...) +#define BSS_TEMP_LOGFUNC(_Fmt...) + +#define SCN_ERROR_LOGFUNC(_Fmt...) +#define SCN_WARN_LOGFUNC(_Fmt...) +#define SCN_INFO_LOGFUNC(_Fmt...) +#define SCN_STATE_LOGFUNC(_Fmt...) +#define SCN_EVENT_LOGFUNC(_Fmt...) +#define SCN_TRACE_LOGFUNC(_Fmt...) +#define SCN_LOUD_LOGFUNC(_Fmt...) +#define SCN_TEMP_LOGFUNC(_Fmt...) + +#define SAA_ERROR_LOGFUNC(_Fmt...) +#define SAA_WARN_LOGFUNC(_Fmt...) +#define SAA_INFO_LOGFUNC(_Fmt...) +#define SAA_STATE_LOGFUNC(_Fmt...) +#define SAA_EVENT_LOGFUNC(_Fmt...) +#define SAA_TRACE_LOGFUNC(_Fmt...) +#define SAA_LOUD_LOGFUNC(_Fmt...) +#define SAA_TEMP_LOGFUNC(_Fmt...) + +#define P2P_ERROR_LOGFUNC(_Fmt...) +#define P2P_WARN_LOGFUNC(_Fmt...) +#define P2P_INFO_LOGFUNC(_Fmt...) +#define P2P_STATE_LOGFUNC(_Fmt...) +#define P2P_EVENT_LOGFUNC(_Fmt...) +#define P2P_TRACE_LOGFUNC(_Fmt...) +#define P2P_LOUD_LOGFUNC(_Fmt...) +#define P2P_TEMP_LOGFUNC(_Fmt...) + +#define QM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_STATE_LOGFUNC(_Fmt...) +#define QM_EVENT_LOGFUNC(_Fmt...) +#define QM_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_LOUD_LOGFUNC(_Fmt...) +#define QM_TEMP_LOGFUNC(_Fmt...) + +#define SEC_ERROR_LOGFUNC(_Fmt...) +#define SEC_WARN_LOGFUNC(_Fmt...) +#define SEC_INFO_LOGFUNC(_Fmt...) +#define SEC_STATE_LOGFUNC(_Fmt...) +#define SEC_EVENT_LOGFUNC(_Fmt...) +#define SEC_TRACE_LOGFUNC(_Fmt...) +#define SEC_LOUD_LOGFUNC(_Fmt...) +#define SEC_TEMP_LOGFUNC(_Fmt...) + +#define BOW_ERROR_LOGFUNC(_Fmt...) +#define BOW_WARN_LOGFUNC(_Fmt...) +#define BOW_INFO_LOGFUNC(_Fmt...) +#define BOW_STATE_LOGFUNC(_Fmt...) +#define BOW_EVENT_LOGFUNC(_Fmt...) +#define BOW_TRACE_LOGFUNC(_Fmt...) +#define BOW_LOUD_LOGFUNC(_Fmt...) +#define BOW_TEMP_LOGFUNC(_Fmt...) + +#define HAL_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define HAL_WARN_LOGFUNC(_Fmt...) +#define HAL_INFO_LOGFUNC(_Fmt...) +#define HAL_STATE_LOGFUNC(_Fmt...) +#define HAL_EVENT_LOGFUNC(_Fmt...) +#define HAL_TRACE_LOGFUNC(_Fmt...) +#define HAL_LOUD_LOGFUNC(_Fmt...) +#define HAL_TEMP_LOGFUNC(_Fmt...) + +#define WAPI_ERROR_LOGFUNC(_Fmt...) +#define WAPI_WARN_LOGFUNC(_Fmt...) +#define WAPI_INFO_LOGFUNC(_Fmt...) +#define WAPI_STATE_LOGFUNC(_Fmt...) +#define WAPI_EVENT_LOGFUNC(_Fmt...) +#define WAPI_TRACE_LOGFUNC(_Fmt...) +#define WAPI_LOUD_LOGFUNC(_Fmt...) +#define WAPI_TEMP_LOGFUNC(_Fmt...) + +#define SW1_ERROR_LOGFUNC(_Fmt...) +#define SW1_WARN_LOGFUNC(_Fmt...) +#define SW1_INFO_LOGFUNC(_Fmt...) +#define SW1_STATE_LOGFUNC(_Fmt...) +#define SW1_EVENT_LOGFUNC(_Fmt...) +#define SW1_TRACE_LOGFUNC(_Fmt...) +#define SW1_LOUD_LOGFUNC(_Fmt...) +#define SW1_TEMP_LOGFUNC(_Fmt...) + +#define SW2_ERROR_LOGFUNC(_Fmt...) +#define SW2_WARN_LOGFUNC(_Fmt...) +#define SW2_INFO_LOGFUNC(_Fmt...) +#define SW2_STATE_LOGFUNC(_Fmt...) +#define SW2_EVENT_LOGFUNC(_Fmt...) +#define SW2_TRACE_LOGFUNC(_Fmt...) +#define SW2_LOUD_LOGFUNC(_Fmt...) +#define SW2_TEMP_LOGFUNC(_Fmt...) + +#define SW3_ERROR_LOGFUNC(_Fmt...) +#define SW3_WARN_LOGFUNC(_Fmt...) +#define SW3_INFO_LOGFUNC(_Fmt...) +#define SW3_STATE_LOGFUNC(_Fmt...) +#define SW3_EVENT_LOGFUNC(_Fmt...) +#define SW3_TRACE_LOGFUNC(_Fmt...) +#define SW3_LOUD_LOGFUNC(_Fmt...) +#define SW3_TEMP_LOGFUNC(_Fmt...) + +#define SW4_ERROR_LOGFUNC(_Fmt...) +#define SW4_WARN_LOGFUNC(_Fmt...) +#define SW4_INFO_LOGFUNC(_Fmt...) +#define SW4_STATE_LOGFUNC(_Fmt...) +#define SW4_EVENT_LOGFUNC(_Fmt...) +#define SW4_TRACE_LOGFUNC(_Fmt...) +#define SW4_LOUD_LOGFUNC(_Fmt...) +#define SW4_TEMP_LOGFUNC(_Fmt...) +#endif +#endif + +#define kalBreakPoint() \ + do { \ + BUG(); \ + panic("Oops"); \ + } while(0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg);} + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in gl_kal.c */ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT PUINT_32 pu4Flags + ); + +VOID +kalReleaseSpinLock( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN UINT_32 u4Flags + ); + +VOID +kalUpdateMACAddress( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucMacAddr + ); + +VOID +kalPacketFree( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket + ); + +PVOID +kalPacketAlloc( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Size, + OUT PUINT_8 *ppucData + ); + +VOID +kalOsTimerInitialize( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID prTimerHandler + ); + +BOOL +kalSetTimer( + IN P_GLUE_INFO_T prGlueInfo, + IN OS_SYSTIME rInterval + ); + +WLAN_STATUS +kalProcessRxPacket( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, + IN PUINT_8 pucPacketStart, + IN UINT_32 u4PacketLen, + //IN PBOOLEAN pfgIsRetain, + IN BOOLEAN fgIsRetain, + IN ENUM_CSUM_RESULT_T aeCSUM[] + ); + +WLAN_STATUS +kalRxIndicatePkts( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID apvPkts[], + IN UINT_8 ucPktNum + ); + +VOID +kalIndicateStatusAndComplete( + IN P_GLUE_INFO_T prGlueInfo, + IN WLAN_STATUS eStatus, + IN PVOID pvBuf, + IN UINT_32 u4BufLen + ); + +VOID +kalUpdateReAssocReqInfo( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, + IN BOOLEAN fgReassocRequest + ); + +VOID +kalUpdateReAssocRspInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen + ); + +#if CFG_TX_FRAGMENT +BOOLEAN +kalQueryTxPacketHeader( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, + OUT PUINT_16 pu2EtherTypeLen, + OUT PUINT_8 pucEthDestAddr + ); +#endif /* CFG_TX_FRAGMENT */ + +VOID +kalSendCompleteAndAwakeQueue( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket + ); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID +kalQueryTxChksumOffloadParam( + IN PVOID pvPacket, + OUT PUINT_8 pucFlag); + +VOID +kalUpdateRxCSUMOffloadParam( + IN PVOID pvPacket, + IN ENUM_CSUM_RESULT_T eCSUM[] + ); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + +BOOLEAN +kalRetrieveNetworkAddress( + IN P_GLUE_INFO_T prGlueInfo, + IN OUT PARAM_MAC_ADDRESS * prMacAddr + ); + + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevRegRead( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Register, + OUT PUINT_32 pu4Value + ); + +BOOL +kalDevRegWrite( + P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Register, + IN UINT_32 u4Value + ); + +BOOL +kalDevPortRead( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, + IN UINT_16 u2Len, + OUT PUINT_8 pucBuf, + IN UINT_16 u2ValidOutBufSize + ); + +BOOL +kalDevPortWrite( + P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, + IN UINT_16 u2Len, + IN PUINT_8 pucBuf, + IN UINT_16 u2ValidInBufSize + ); + +BOOL +kalDevWriteWithSdioCmd52 ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Addr, + IN UINT_8 ucData + ); + + + #if CFG_SUPPORT_EXT_CONFIG +UINT_32 +kalReadExtCfg ( + IN P_GLUE_INFO_T prGlueInfo + ); + #endif + +BOOL +kalQoSFrameClassifierAndPacketInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, + OUT PUINT_8 pucNetworkType +); + +inline VOID +kalOidComplete ( + IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, + IN UINT_32 u4SetQueryInfoLen, + IN WLAN_STATUS rOidStatus + ); + + +WLAN_STATUS +kalIoctl (IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOL fgRead, + IN BOOL fgWaitResp, + IN BOOL fgCmd, + IN BOOL fgIsP2pOid, + OUT PUINT_32 pu4QryInfoLen + ); + +VOID +kalHandleAssocInfo( + IN P_GLUE_INFO_T prGlueInfo, + IN P_EVENT_ASSOC_INFO prAssocInfo + ); + +#if CFG_ENABLE_FW_DOWNLOAD + +PVOID +kalFirmwareImageMapping ( + IN P_GLUE_INFO_T prGlueInfo, + OUT PPVOID ppvMapFileBuf, + OUT PUINT_32 pu4FileLength + ); + +VOID +kalFirmwareImageUnmapping ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID prFwHandle, + IN PVOID pvMapFileBuf + ); +#endif + + +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalIsCardRemoved( + IN P_GLUE_INFO_T prGlueInfo + ); + + +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +VOID +kalFlushPendingTxPackets( + IN P_GLUE_INFO_T prGlueInfo + ); + + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T +kalGetMediaStateIndicated( + IN P_GLUE_INFO_T prGlueInfo + ); + + +VOID +kalSetMediaStateIndicated( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate + ); + + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +VOID +kalOidCmdClearance( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalOidClearance( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalEnqueueCommand( + IN P_GLUE_INFO_T prGlueInfo, + IN P_QUE_ENTRY_T prQueueEntry + ); + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBOWEvent( + IN P_GLUE_INFO_T prGlueInfo, + IN P_AMPC_EVENT prEvent + ); + +ENUM_BOW_DEVICE_STATE +kalGetBowState ( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr + ); + +BOOLEAN +kalSetBowState ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BOW_DEVICE_STATE eBowState, + PARAM_MAC_ADDRESS rPeerAddr + ); + +ENUM_BOW_DEVICE_STATE +kalGetBowGlobalState ( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_32 +kalGetBowFreqInKHz( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_8 +kalGetBowRole( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr + ); + +VOID +kalSetBowRole( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRole, + IN PARAM_MAC_ADDRESS rPeerAddr + ); + +UINT_8 +kalGetBowAvailablePhysicalLinkCount( + IN P_GLUE_INFO_T prGlueInfo + ); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalInitBowDevice( + IN P_GLUE_INFO_T prGlueInfo, + IN const char *prDevName + ); + +BOOLEAN +kalUninitBowDevice( + IN P_GLUE_INFO_T prGlueInfo + ); +#endif // CFG_BOW_SEPARATE_DATA_PATH +#endif // CFG_ENABLE_BT_OVER_WIFI + + +/*----------------------------------------------------------------------------*/ +/* Firmware Download Handling */ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetFwStartAddress( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_32 +kalGetFwLoadAddress( + IN P_GLUE_INFO_T prGlueInfo + ); + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID +kalClearSecurityFrames( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalClearSecurityFramesByNetType( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +VOID +kalSecurityFrameSendComplete ( + IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, + IN WLAN_STATUS rStatus + ); + + +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID +kalClearMgmtFrames( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalClearMgmtFramesByNetType( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx + ); + +UINT_32 +kalGetTxPendingFrameCount( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_32 +kalGetTxPendingCmdCount( + IN P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +kalSetTimer( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Interval + ); + +BOOLEAN +kalCancelTimer( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalScanDone( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN WLAN_STATUS status + ); + +UINT_32 +kalRandomNumber( + VOID + ); + +VOID +kalTimeoutHandler (unsigned long arg); + +VOID +kalSetEvent (P_GLUE_INFO_T pr); + + +/*----------------------------------------------------------------------------*/ +/* NVRAM/Registry Service */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalIsConfigurationExist( + IN P_GLUE_INFO_T prGlueInfo + ); + +P_REG_INFO_T +kalGetConfiguration( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalGetConfigurationVersion( + IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, + OUT PUINT_16 pu2Part2CfgPeerVersion + ); + +BOOLEAN +kalCfgDataRead16( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Offset, + OUT PUINT_16 pu2Data + ); + +BOOLEAN +kalCfgDataWrite16( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Offset, + IN UINT_16 u2Data + ); + +/*----------------------------------------------------------------------------*/ +/* WSC Connection */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalWSCGetActiveState( + IN P_GLUE_INFO_T prGlueInfo + ); + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, + IN INT_8 cRssi, + IN INT_8 cLinkQuality + ); + + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalInitIOBuffer( + VOID + ); + +VOID +kalUninitIOBuffer( + VOID + ); + +PVOID +kalAllocateIOBuffer( + IN UINT_32 u4AllocSize + ); + +VOID +kalReleaseIOBuffer( + IN PVOID pvAddr, + IN UINT_32 u4Size + ); + +VOID +kalGetChannelList( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, + IN PUINT_8 pucNumOfChannel, + IN P_RF_CHANNEL_INFO_T paucChannelList + ); + +BOOL +kalIsAPmode( + IN P_GLUE_INFO_T prGlueInfo + ); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +UINT_32 +kalGetMfpSetting( + IN P_GLUE_INFO_T prGlueInfo + ); +#endif + +UINT_32 +kalWriteToFile( + const PUINT_8 pucPath, + BOOLEAN fgDoAppend, + PUINT_8 pucData, + UINT_32 u4Size + ); + + +/*----------------------------------------------------------------------------*/ +/* NL80211 */ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBssInfo ( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, + IN UINT_8 ucChannelNum, + IN INT_32 i4SignalStrength + ); + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int tx_thread(void *data); + +#endif /* _GL_KAL_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h new file mode 100755 index 000000000000..4a5c3dc882c3 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h @@ -0,0 +1,1140 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_os.h#2 $ +*/ + +/*! \file gl_os.h + \brief List the external reference to OS for GLUE Layer. + + In this file we define the data structure - GLUE_INFO_T to store those objects + we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the + external reference (header file, extern func() ..) to OS for GLUE Layer should + also list down here. +*/ + + + +/* +** $Log: gl_os.h $ +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. +** +** 08 20 2012 yuche.tsai +** [ALPS00339327] [Rose][6575JB][BSP Package][Free Test][KE][WIFI]There is no response when you tap the turn off/on button,wait a minutes, the device will reboot automatically and "KE" will pop up. +** Fix possible KE when netlink operate mgmt frame register. + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 16 2011 yuche.tsai + * NULL + * Avoid using work thread. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 29 2011 terry.wu + * NULL + * Show DRV_NAME by chip id. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 02 16 2011 jeffrey.chang + * NULL + * Add query ipv4 and ipv6 address during early suspend and late resume + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module with structure miss-align pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 02 09 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Halt p2p module init and exit until TxThread finished p2p register and unregister. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information + * fill mac header length information for 802.1x frames. + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 13 2010 cp.wu + * NULL + * add waitq for poll() and read(). + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 23 2010 jeffrey.chang + * + * add new KAL api + * + * 07 22 2010 jeffrey.chang + * + * modify tx thread and remove some spinlock + * + * 07 19 2010 jeffrey.chang + * + * add security frame pending count + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change variable names for multiple physical link to match with coding convention + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * supporting power management + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * pvInformationBuffer and u4InformationBufferLength are no longer in glue + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * * * are done in adapter layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Tag the packet for QoS on Tx path + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)deliver the kalOidComplete status to upper layer + * * (2) fix spin lock + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download related data type + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * * * the frequency is used for adhoc connection only + * * * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 25 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add Bluetooth-over-Wifi frame header check + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\30 2009-10-20 17:38:31 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw. +** \main\maintrunk.MT5921\29 2009-10-08 10:33:33 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers. +** \main\maintrunk.MT5921\28 2009-09-28 20:19:26 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\27 2009-08-18 22:57:12 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\26 2009-07-06 21:42:25 GMT mtk01088 +** fixed the compiling error at linux +** \main\maintrunk.MT5921\25 2009-07-06 20:51:46 GMT mtk01088 +** adding the wapi 1x ether type define +** \main\maintrunk.MT5921\24 2009-06-23 23:19:18 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\23 2009-02-07 15:05:06 GMT mtk01088 +** add the privacy flag to ingo driver the supplicant selected ap's security +** \main\maintrunk.MT5921\22 2009-02-05 15:34:09 GMT mtk01088 +** fixed the compiling error for using bits marco for only one parameter +** \main\maintrunk.MT5921\21 2009-01-22 13:02:13 GMT mtk01088 +** data frame is or not 802.1x value share with tid, using the same reserved byte, provide the function to set and get +** \main\maintrunk.MT5921\20 2008-10-24 12:04:16 GMT mtk01088 +** move the config.h from precomp.h to here for lint check +** \main\maintrunk.MT5921\19 2008-09-22 23:19:02 GMT mtk01461 +** Update driver for code review +** \main\maintrunk.MT5921\18 2008-09-05 17:25:13 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\17 2008-08-01 13:32:47 GMT mtk01084 +** Prevent redundent driver assertion in driver logic when BUS is detached +** \main\maintrunk.MT5921\16 2008-05-30 14:41:43 GMT mtk01461 +** Remove WMM Assoc Flag in KAL +** \main\maintrunk.MT5921\15 2008-05-29 14:16:25 GMT mtk01084 +** remoev un-used variable +** \main\maintrunk.MT5921\14 2008-05-03 15:17:14 GMT mtk01461 +** Add Media Status variable in Glue Layer +** \main\maintrunk.MT5921\13 2008-04-24 11:58:41 GMT mtk01461 +** change threshold to 256 +** \main\maintrunk.MT5921\12 2008-03-11 14:51:05 GMT mtk01461 +** Remove redundant GL_CONN_INFO_T +** \main\maintrunk.MT5921\11 2008-01-07 15:07:41 GMT mtk01461 +** Adjust the netif stop threshold to 150 +** \main\maintrunk.MT5921\10 2007-11-26 19:43:46 GMT mtk01461 +** Add OS_TIMESTAMP macro +** +** \main\maintrunk.MT5921\9 2007-11-07 18:38:38 GMT mtk01461 +** Move definition +** \main\maintrunk.MT5921\8 2007-11-02 01:04:00 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** Revision 1.5 2007/07/12 11:04:28 MTK01084 +** update macro to delay for ms order +** +** Revision 1.4 2007/07/05 07:25:34 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +#ifndef _GL_OS_H +#define _GL_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +/*------------------------------------------------------------------------------ + * Flags for LINUX(OS) dependent + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_WLAN_DEVICES 1 /* number of wlan card will coexist*/ + +#define CFG_MAX_TXQ_NUM 4 /* number of tx queue for support multi-queue h/w */ + + +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 0 /* 1: Enable use of SPIN LOCK Bottom Half for LINUX + 0: Disable - use SPIN LOCK IRQ SAVE instead */ + +#define CFG_TX_PADDING_SMALL_ETH_PACKET 0 /* 1: Enable - Drop ethernet packet if it < 14 bytes. + And pad ethernet packet with dummy 0 if it < 60 bytes. + 0: Disable */ + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 64 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 32 /* packets */ + + +#define ETH_P_1X 0x888E +#define IPTOS_PREC_OFFSET 5 +#define USER_PRIORITY_DEFAULT 0 + +#define ETH_WPI_1X 0x88B4 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 +#define ETH_P_IP 0x0800 +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 + +#define IPVERSION 4 +#define IP_HEADER_LEN 20 + +#define IPVH_VERSION_OFFSET 4 // For Little-Endian +#define IPVH_VERSION_MASK 0xF0 +#define IPTOS_PREC_OFFSET 5 +#define IPTOS_PREC_MASK 0xE0 + +#define SOURCE_PORT_LEN 2 +/* NOTE(Kevin): Without IP Option Length */ +#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETH_HLEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETH_HLEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_BT_SIG_OUI_0 0x00 +#define ETH_SNAP_BT_SIG_OUI_1 0x19 +#define ETH_SNAP_BT_SIG_OUI_2 0x58 + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + + +#if defined(MT6620) + #define CHIP_NAME "MT6620" +#elif defined(MT5931) + #define CHIP_NAME "MT5931" +#elif defined(MT6628) + #define CHIP_NAME "MT6628" +#endif + +#define DRV_NAME "["CHIP_NAME"]: " + +/* Define if target platform is Android. + * It should already be defined in Android kernel source + */ +#ifndef CONFIG_ANDROID +#define CONFIG_ANDROID 0 +#endif + +/* for CFG80211 IE buffering mechanism */ +#define CFG_CFG80211_IE_BUF_LEN (512) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#include +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12) +#include /* IRQT_FALLING */ +#include /*for in_interrupt*/ +#endif + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#if defined(_HIF_SDIO) +#include +#include +#endif + +#include + +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#if CFG_CHIP_RESET_SUPPORT + #include "gl_rst.h" +#endif +#include "hif.h" + + +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +extern BOOLEAN fgIsBusAccessFailed; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GLUE_FLAG_HALT BIT(0) +#define GLUE_FLAG_INT BIT(1) +#define GLUE_FLAG_OID BIT(2) +#define GLUE_FLAG_TIMEOUT BIT(3) +#define GLUE_FLAG_TXREQ BIT(4) +#define GLUE_FLAG_SUB_MOD_INIT BIT(5) +#define GLUE_FLAG_SUB_MOD_EXIT BIT(6) +#define GLUE_FLAG_SUB_MOD_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_HALT_BIT (0) +#define GLUE_FLAG_INT_BIT (1) +#define GLUE_FLAG_OID_BIT (2) +#define GLUE_FLAG_TIMEOUT_BIT (3) +#define GLUE_FLAG_TXREQ_BIT (4) +#define GLUE_FLAG_SUB_MOD_INIT_BIT (5) +#define GLUE_FLAG_SUB_MOD_EXIT_BIT (6) +#define GLUE_FLAG_SUB_MOD_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) + + + +#define GLUE_BOW_KFIFO_DEPTH (1024) +//#define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" +#define GLUE_BOW_DEVICE_NAME "ampc0" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _GL_WPA_INFO_T { + UINT_32 u4WpaVersion; + UINT_32 u4KeyMgmt; + UINT_32 u4CipherGroup; + UINT_32 u4CipherPairwise; + UINT_32 u4AuthAlg; + BOOLEAN fgPrivacyInvoke; +#if CFG_SUPPORT_802_11W + UINT_32 u4Mfp; +#endif +} GL_WPA_INFO_T, *P_GL_WPA_INFO_T; + +typedef enum _ENUM_RSSI_TRIGGER_TYPE { + ENUM_RSSI_TRIGGER_NONE, + ENUM_RSSI_TRIGGER_GREATER, + ENUM_RSSI_TRIGGER_LESS, + ENUM_RSSI_TRIGGER_TRIGGERED, + ENUM_RSSI_TRIGGER_NUM +} ENUM_RSSI_TRIGGER_TYPE; + +#if CFG_ENABLE_WIFI_DIRECT +typedef enum _ENUM_SUB_MODULE_IDX_T { + P2P_MODULE = 0, + SUB_MODULE_NUM +} ENUM_SUB_MODULE_IDX_T; + +typedef enum _ENUM_NET_REG_STATE_T { + ENUM_NET_REG_STATE_UNREGISTERED, + ENUM_NET_REG_STATE_REGISTERING, + ENUM_NET_REG_STATE_REGISTERED, + ENUM_NET_REG_STATE_UNREGISTERING, + ENUM_NET_REG_STATE_NUM +} ENUM_NET_REG_STATE_T; + +#endif + +typedef struct _GL_IO_REQ_T { + QUE_ENTRY_T rQueEntry; + //wait_queue_head_t cmdwait_q; + BOOL fgRead; + BOOL fgWaitResp; +#if CFG_ENABLE_WIFI_DIRECT + BOOL fgIsP2pOid; +#endif + P_ADAPTER_T prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + PVOID pvInfoBuf; + UINT_32 u4InfoBufLen; + PUINT_32 pu4QryInfoLen; + WLAN_STATUS rStatus; + UINT_32 u4Flag; +} GL_IO_REQ_T, *P_GL_IO_REQ_T; + +#if CFG_ENABLE_BT_OVER_WIFI +typedef struct _GL_BOW_INFO { + BOOLEAN fgIsRegistered; + dev_t u4DeviceNumber; /* dynamic device number */ +// struct kfifo *prKfifo; /* for buffering indicated events */ + struct kfifo rKfifo; /* for buffering indicated events */ + spinlock_t rSpinLock; /* spin lock for kfifo */ + struct cdev cdev; + UINT_32 u4FreqInKHz; /* frequency */ + + UINT_8 aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, 1: Initiator */ + ENUM_BOW_DEVICE_STATE aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + PARAM_MAC_ADDRESS arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM]; + + wait_queue_head_t outq; + + #if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + BOOLEAN fgIsNetRegistered; + #endif + +} GL_BOW_INFO, *P_GL_BOW_INFO; +#endif + +/* +* type definition of pointer to p2p structure +*/ +typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; + +struct _GLUE_INFO_T { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device Index(index of arWlanDevInfo[]) */ + INT_32 i4DevIdx; + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* Wireless statistics struct net_device */ + struct iw_statistics rIwStats; + + /* spinlock to sync power save mechanism */ + spinlock_t rSpinLock[SPIN_LOCK_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + UINT_32 u4Flag; /* GLUE_FLAG_XXX */ + UINT_32 u4PendFlag; + //UINT_32 u4TimeoutFlag; + UINT_32 u4OidCompleteFlag; + UINT_32 u4ReadyFlag; /* check if card is ready */ + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + INT_32 ai4TxPendingFrameNumPerQueue[4][CFG_MAX_TXQ_NUM]; + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + + /* current IO request for kalIoctl */ + GL_IO_REQ_T OidEntry; + + /* registry info*/ + REG_INFO_T rRegInfo; + + /* firmware */ + struct firmware *prFw; + + /* Host interface related information */ + /* defined in related hif header file */ + GL_HIF_INFO_T rHifInfo; + + /*! \brief wext wpa related information */ + GL_WPA_INFO_T rWpaInfo; + + + /* Pointer to ADAPTER_T - main data structure of internal protocol stack */ + P_ADAPTER_T prAdapter; + +#ifdef WLAN_INCLUDE_PROC + struct proc_dir_entry *pProcRoot; +#endif /* WLAN_INCLUDE_PROC */ + + /* Indicated media state */ + ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicated; + + /* Device power state D0~D3 */ + PARAM_DEVICE_POWER_STATE ePowerState; + + struct completion rScanComp; /* indicate scan complete */ + struct completion rHaltComp; /* indicate main thread halt complete */ + struct completion rPendComp; /* indicate main thread halt complete */ +#if CFG_ENABLE_WIFI_DIRECT + struct completion rSubModComp; /*indicate sub module init or exit complete*/ +#endif + WLAN_STATUS rPendStatus; + + QUE_T rTxQueue; + + + /* OID related */ + QUE_T rCmdQueue; + //PVOID pvInformationBuffer; + //UINT_32 u4InformationBufferLength; + //PVOID pvOidEntry; + //PUINT_8 pucIOReqBuff; + //QUE_T rIOReqQueue; + //QUE_T rFreeIOReqQueue; + + wait_queue_head_t waitq; + struct task_struct *main_thread; + + struct timer_list tickfn; + + +#if CFG_SUPPORT_EXT_CONFIG + UINT_16 au2ExtCfg[256]; /* NVRAM data buffer */ + UINT_32 u4ExtCfgLength; /* 0 means data is NOT valid */ +#endif + +#if 1//CFG_SUPPORT_WAPI + /* Should be large than the PARAM_WAPI_ASSOC_INFO_T */ + UINT_8 aucWapiAssocInfoIEs[42]; + UINT_16 u2WapiAssocInfoIESz; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + GL_BOW_INFO rBowInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + P_GL_P2P_INFO_T prP2PInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* Wireless statistics struct net_device */ + struct iw_statistics rP2pIwStats; +#endif +#endif + BOOLEAN fgWpsActive; + UINT_8 aucWSCIE[500]; /*for probe req*/ + UINT_16 u2WSCIELen; + UINT_8 aucWSCAssocInfoIE[200]; /*for Assoc req*/ + UINT_16 u2WSCAssocInfoIELen; + + /* NVRAM availability */ + BOOLEAN fgNvramAvailable; + + BOOLEAN fgMcrAccessAllowed; + + /* MAC Address Overriden by IOCTL */ + BOOLEAN fgIsMacAddrOverride; + PARAM_MAC_ADDRESS rMacAddrOverride; + + SET_TXPWR_CTRL_T rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* to indicate registered or not */ + BOOLEAN fgIsRegistered; + + /* for cfg80211 connected indication */ + UINT_32 u4RspIeLength; + UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + UINT_32 u4ReqIeLength; + UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + /* linux 2.4 */ + typedef void (*PFN_WLANISR)(int irq, void *dev_id, struct pt_regs *regs); +#else + typedef irqreturn_t (*PFN_WLANISR)(int irq, void *dev_id, struct pt_regs *regs); +#endif + +typedef void (*PFN_LINUX_TIMER_FUNC)(unsigned long); + + +/* generic sub module init/exit handler +* now, we only have one sub module, p2p +*/ +#if CFG_ENABLE_WIFI_DIRECT +typedef BOOLEAN (*SUB_MODULE_INIT)(P_GLUE_INFO_T prGlueInfo); +typedef BOOLEAN (*SUB_MODULE_EXIT)(P_GLUE_INFO_T prGlueInfo); + +typedef struct _SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + BOOLEAN fgIsInited; +} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; + +#endif + +#if CONFIG_NL80211_TESTMODE + +typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; + +/*SW CMD */ +typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 set; + unsigned long adr; + unsigned long data; +}NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; + +struct iw_encode_exts { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 addr[MAC_ADDR_LEN]; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +typedef struct _NL80211_DRIVER_SET_KEY_EXTS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 key_index; + UINT_8 key_len; + struct iw_encode_exts ext; +}NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; + + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Glue Layer */ +/*----------------------------------------------------------------------------*/ +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + #define GLUE_SPIN_LOCK_DECLARATION() + #define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } + #define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + #define GLUE_SPIN_LOCK_DECLARATION() UINT_32 __u4Flags = 0 + #define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __u4Flags); \ + } + #define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __u4Flags); \ + } +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&( ((struct sk_buff *)(_p))->cb[0] )) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((P_NATIVE_PACKET) ((UINT_32)_prQueueEntry - offsetof(struct sk_buff, cb[0])) ) + +#define GLUE_SET_PKT_FLAG_802_11(_p) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(7)) + +#define GLUE_SET_PKT_FLAG_1X(_p) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(6)) + +#define GLUE_SET_PKT_FLAG_PAL(_p) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(5)) + +#define GLUE_SET_PKT_FLAG_P2P(_p) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(4)) + + + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= (((UINT_8)((_tid) & (BITS(0,3)))))) + + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (*((PUINT_16) &( ((struct sk_buff *)(_p))->cb[6] )) = (UINT_16)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (*((PUINT_16) &( ((struct sk_buff *)(_p))->cb[6] )) ) + + +#define GLUE_GET_PKT_IS_802_11(_p) \ + ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(7))) + +#define GLUE_GET_PKT_IS_1X(_p) \ + ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(6))) + +#define GLUE_GET_PKT_TID(_p) \ + ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BITS(0,3))) + + +#define GLUE_GET_PKT_IS_PAL(_p) \ + ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(5))) + +#define GLUE_GET_PKT_IS_P2P(_p) \ + ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(4))) + + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[5] )) = (UINT_8)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[5] )) ) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (*((POS_SYSTIME) &( ((struct sk_buff *)(_p))->cb[8] )) = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (*((POS_SYSTIME) &( ((struct sk_buff *)(_p))->cb[8] )) ) + +/* Check validity of prDev, private data, and pointers */ +#define GLUE_CHK_DEV(prDev) \ + ((prDev && *((P_GLUE_INFO_T *) netdev_priv(prDev))) ? TRUE : FALSE) + +#define GLUE_CHK_PR2(prDev, pr2) \ + ((GLUE_CHK_DEV(prDev) && pr2) ? TRUE : FALSE) + +#define GLUE_CHK_PR3(prDev, pr2, pr3) \ + ((GLUE_CHK_PR2(prDev, pr2) && pr3) ? TRUE : FALSE) + +#define GLUE_CHK_PR4(prDev, pr2, pr3, pr4) \ + ((GLUE_CHK_PR3(prDev, pr2, pr3) && pr4) ? TRUE : FALSE) + +#define GLUE_SET_EVENT(pr) \ + kalSetEvent(pr) + +#define GLUE_INC_REF_CNT(_refCount) atomic_inc((atomic_t *)&(_refCount)) +#define GLUE_DEC_REF_CNT(_refCount) atomic_dec((atomic_t *)&(_refCount)) + + +#define DbgPrint(...) +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef WLAN_INCLUDE_PROC +INT_32 +procRemoveProcfs ( + struct net_device *prDev, + char *pucDevName + ); + +INT_32 +procInitProcfs ( + struct net_device *prDev, + char *pucDevName + ); +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI +BOOLEAN +glRegisterAmpc ( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +glUnregisterAmpc ( + P_GLUE_INFO_T prGlueInfo + ); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + +VOID +wlanSubModRunInit( + P_GLUE_INFO_T prGlueInfo + ); + +VOID +wlanSubModRunExit( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +wlanSubModInit( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +wlanSubModExit( + P_GLUE_INFO_T prGlueInfo + ); + +VOID +wlanSubModRegisterInitExit( + SUB_MODULE_INIT rSubModInit, + SUB_MODULE_EXIT rSubModExit, + ENUM_SUB_MODULE_IDX_T eSubModIdx + ); + +BOOLEAN +wlanExportGlueInfo( + P_GLUE_INFO_T *prGlueInfoExpAddr + ); + +BOOLEAN +wlanIsLaunched( + VOID + ); + +void +p2pSetMulticastListWorkQueueWrapper( + P_GLUE_INFO_T prGlueInfo + ); + + + +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_OS_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h new file mode 100755 index 000000000000..9c2ec9dfd9b9 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,1098 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_ioctl.h#9 $ +*/ + +/*! \file gl_p2p_ioctl.h + \brief This file is for custom ioctls for Wi-Fi Direct only +*/ + + + +/* +** $Log: gl_p2p_ioctl.h $ +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 03 25 2011 wh.su + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * . + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 16 2011 chinglan.wang + * NULL + * Add the group id information in the invitation indication. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 05 04 2011 chinglan.wang + * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver + * . + * + * 03 29 2011 wh.su + * [WCXRP00000095] [MT6620 Wi-Fi] [FW] Refine the P2P GO send broadcast protected code + * add the set power and get power function sample. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 01 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * fixed the ioctl sumcmd to meet the p2p_supplicant setting. + * + * 02 23 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int define for p2p parameter. + * + * 02 22 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int from supplicant, and can used to set the p2p paramters + * + * 02 17 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * adjust the set wsc ie structure. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 12 15 2010 cp.wu + * NULL + * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() + * + * 12 07 2010 cp.wu + * [WCXRP00000237] [MT6620 Wi-Fi][Wi-Fi Direct][Driver] Add interface for supporting service discovery + * define a pair of i/o control for multiplexing layer + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 10 2010 george.huang + * NULL + * update iwpriv LP related + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 08 25 2010 cp.wu + * NULL + * add netdev_ops(NDO) for linux kernel 2.6.31 or greater + * + * 08 20 2010 yuche.tsai + * NULL + * Refine a function parameter name. + * + * 08 19 2010 cp.wu + * NULL + * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. + * + * 08 16 2010 george.huang + * NULL + * add wext handlers to link P2P set PS profile/ network address function (TBD) + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 12 2010 cp.wu + * NULL + * follow-up with ioctl interface update for Wi-Fi Direct application + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement wireless extension ioctls in iw_handler form. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * +*/ + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + #include + #include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +// (WirelessExtension) Private I/O Controls +#define IOC_P2P_CFG_DEVICE (SIOCIWFIRSTPRIV+0) +#define IOC_P2P_PROVISION_COMPLETE (SIOCIWFIRSTPRIV+2) +#define IOC_P2P_START_STOP_DISCOVERY (SIOCIWFIRSTPRIV+4) +#define IOC_P2P_DISCOVERY_RESULTS (SIOCIWFIRSTPRIV+5) +#define IOC_P2P_WSC_BEACON_PROBE_RSP_IE (SIOCIWFIRSTPRIV+6) +#define IOC_P2P_GO_WSC_IE IOC_P2P_WSC_BEACON_PROBE_RSP_IE +#define IOC_P2P_CONNECT_DISCONNECT (SIOCIWFIRSTPRIV+8) +#define IOC_P2P_PASSWORD_READY (SIOCIWFIRSTPRIV+10) +//#define IOC_P2P_SET_PWR_MGMT_PARAM (SIOCIWFIRSTPRIV+12) +#define IOC_P2P_SET_INT (SIOCIWFIRSTPRIV+12) +#define IOC_P2P_GET_STRUCT (SIOCIWFIRSTPRIV+13) +#define IOC_P2P_SET_STRUCT (SIOCIWFIRSTPRIV+14) +#define IOC_P2P_GET_REQ_DEVICE_INFO (SIOCIWFIRSTPRIV+15) + +#define PRIV_CMD_INT_P2P_SET 0 + +// IOC_P2P_PROVISION_COMPLETE (iw_point . flags) +#define P2P_PROVISIONING_SUCCESS 0 +#define P2P_PROVISIONING_FAIL 1 + +// IOC_P2P_START_STOP_DISCOVERY (iw_point . flags) +#define P2P_STOP_DISCOVERY 0 +#define P2P_START_DISCOVERY 1 + +// IOC_P2P_CONNECT_DISCONNECT (iw_point . flags) +#define P2P_CONNECT 0 +#define P2P_DISCONNECT 1 + +// IOC_P2P_START_STOP_DISCOVERY (scan_type) +#define P2P_SCAN_FULL_AND_FIND 0 +#define P2P_SCAN_FULL 1 +#define P2P_SCAN_SEARCH_AND_LISTEN 2 +#define P2P_LISTEN 3 + +// IOC_P2P_GET_STRUCT/IOC_P2P_SET_STRUCT +#define P2P_SEND_SD_RESPONSE 0 +#define P2P_GET_SD_REQUEST 1 +#define P2P_SEND_SD_REQUEST 2 +#define P2P_GET_SD_RESPONSE 3 +#define P2P_TERMINATE_SD_PHASE 4 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*----------------------------------------------------------------------------*/ +typedef struct iw_p2p_cfg_device_type { + void __user *ssid; + UINT_8 ssid_len; + UINT_8 pri_device_type[8]; + UINT_8 snd_device_type[8]; + void __user *device_name; + UINT_8 device_name_len; + UINT_8 intend; + UINT_8 persistence; + UINT_8 sec_mode; + UINT_8 ch; + UINT_8 ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + UINT_8 max_scb; +} IW_P2P_CFG_DEVICE_TYPE, *P_IW_P2P_CFG_DEVICE_TYPE; + +typedef struct iw_p2p_hostapd_param { + UINT_8 cmd; + UINT_8 rsv[3]; + UINT_8 sta_addr[6]; + void __user *data; + UINT_16 len; +} IW_P2P_HOSTAPD_PARAM, *P_IW_P2P_HOSTAPD_PARAM; + +typedef struct iw_p2p_req_device_type { + UINT_8 scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + UINT_8 pri_device_type[8]; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_REQ_DEVICE_TYPE, *P_IW_P2P_REQ_DEVICE_TYPE; + +typedef struct iw_p2p_connect_device { + UINT_8 sta_addr[6]; + UINT_8 p2pRole; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 authPeer; /* 1: auth peer invitation request */ + UINT_8 intend_config_method; /* Request Peer Device used config method */ +} IW_P2P_CONNECT_DEVICE, *P_IW_P2P_CONNECT_DEVICE; + +typedef struct iw_p2p_password_ready { + UINT_8 active_config_method; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_PASSWORD_READY, *P_IW_P2P_PASSWORD_READY; + +typedef struct iw_p2p_device_req { + UINT_8 name[33]; + UINT_32 name_len; + UINT_8 device_addr[6]; + UINT_8 device_type; + INT_32 config_method; + INT_32 active_config_method; +} IW_P2P_DEVICE_REQ, *P_IW_P2P_DEVICE_REQ; + +typedef struct iw_p2p_transport_struct { + UINT_32 u4CmdId; + UINT_32 inBufferLength; + UINT_32 outBufferLength; + UINT_8 aucBuffer[16]; +} IW_P2P_TRANSPORT_STRUCT, *P_IW_P2P_TRANSPORT_STRUCT; + +// For Invitation +typedef struct iw_p2p_ioctl_invitation_struct { + UINT_8 aucDeviceID[6]; + UINT_8 aucGroupID[6]; // BSSID + UINT_8 aucSsid[32]; + UINT_32 u4SsidLen; + UINT_8 ucReinvoke; +} IW_P2P_IOCTL_INVITATION_STRUCT, *P_IW_P2P_IOCTL_INVITATION_STRUCT; + +typedef struct iw_p2p_ioctl_abort_invitation { + UINT_8 dev_addr[6]; +} IW_P2P_IOCTL_ABORT_INVITATION, *P_IW_P2P_IOCTL_ABORT_INVITATION; + +typedef struct iw_p2p_ioctl_invitation_indicate { + UINT_8 dev_addr[6]; + UINT_8 group_bssid[6]; + INT_32 config_method; /* peer device supported config method */ + UINT_8 dev_name[32]; /* for reinvoke */ + UINT_32 name_len; + UINT_8 operating_channel; /* for re-invoke, target operating channel */ + UINT_8 invitation_type; /* invitation or re-invoke */ +} IW_P2P_IOCTL_INVITATION_INDICATE, *P_IW_P2P_IOCTL_INVITATION_INDICATE; + +typedef struct iw_p2p_ioctl_invitation_status { + UINT_32 status_code; +} IW_P2P_IOCTL_INVITATION_STATUS, *P_IW_P2P_IOCTL_INVITATION_STATUS; + +//For Formation +typedef struct iw_p2p_ioctl_start_formation { + UINT_8 dev_addr[6]; /* bssid */ + UINT_8 role; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 auth; /* 1: auth peer invitation request */ + UINT_8 config_method; /* Request Peer Device used config method */ +}IW_P2P_IOCTL_START_FORMATION, *P_IW_P2P_IOCTL_START_FORMATION; + +/* SET_STRUCT / GET_STRUCT */ +typedef enum _ENUM_P2P_CMD_ID_T { + P2P_CMD_ID_SEND_SD_RESPONSE = 0, /* 0x00 (Set) */ + P2P_CMD_ID_GET_SD_REQUEST, /* 0x01 (Get) */ + P2P_CMD_ID_SEND_SD_REQUEST, /* 0x02 (Set) */ + P2P_CMD_ID_GET_SD_RESPONSE, /* 0x03 (Get) */ + P2P_CMD_ID_TERMINATE_SD_PHASE, /* 0x04 (Set) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + P2P_CMD_ID_SEC_CHECK, /* 0x05(Set) */ +#endif + P2P_CMD_ID_INVITATION, /* 0x06 (Set) */ + P2P_CMD_ID_INVITATION_INDICATE, /* 0x07 (Get) */ + P2P_CMD_ID_INVITATION_STATUS, /* 0x08 (Get) */ + P2P_CMD_ID_INVITATION_ABORT, /* 0x09 (Set) */ + P2P_CMD_ID_START_FORMATION, /* 0x0A (Set) */ + P2P_CMD_ID_P2P_VERSION, /* 0x0B (Set/Get) */ + P2P_CMD_ID_GET_CH_LIST = 12, /* 0x0C (Get) */ + P2P_CMD_ID_GET_OP_CH = 14 /* 0x0E (Get) */ +} ENUM_P2P_CMD_ID_T, *P_ENUM_P2P_CMD_ID_T; + +/* Service Discovery */ +typedef struct iw_p2p_cmd_send_sd_response { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} IW_P2P_CMD_SEND_SD_RESPONSE, *P_IW_P2P_CMD_SEND_SD_RESPONSE; + +typedef struct iw_p2p_cmd_get_sd_request { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} IW_P2P_CMD_GET_SD_REQUEST, *P_IW_P2P_CMD_GET_SD_REQUEST; + +typedef struct iw_p2p_cmd_send_service_discovery_request { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} IW_P2P_CMD_SEND_SD_REQUEST, *P_IW_P2P_CMD_SEND_SD_REQUEST; + +typedef struct iw_p2p_cmd_get_sd_response { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11*/ +} IW_P2P_CMD_GET_SD_RESPONSE, *P_IW_P2P_CMD_GET_SD_RESPONSE; + +typedef struct iw_p2p_cmd_terminate_sd_phase { + PARAM_MAC_ADDRESS rPeerAddr; +} IW_P2P_CMD_TERMINATE_SD_PHASE, *P_IW_P2P_CMD_TERMINATE_SD_PHASE; + +typedef struct iw_p2p_version { + UINT_32 u4Version; +} IW_P2P_VERSION, *P_IW_P2P_VERSION; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Macros used for cfg80211 */ +#define RATETAB_ENT(_rate, _rateid, _flags) \ + { \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ + } + +#define CHAN2G(_channel, _freq, _flags) \ + { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ + } + +#define CHAN5G(_channel, _flags) \ + { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_p2p_cfg80211_change_iface( + struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params + ); + +int mtk_p2p_cfg80211_add_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + struct key_params *params + ); + +int mtk_p2p_cfg80211_get_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*) + ); + +int mtk_p2p_cfg80211_del_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr + ); + +int +mtk_p2p_cfg80211_set_default_key( + struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index, + bool unicast, + bool multicast + ); + + +int mtk_p2p_cfg80211_get_station( + struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo + ); + +int mtk_p2p_cfg80211_scan( + struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_scan_request *request + ); + +int mtk_p2p_cfg80211_set_wiphy_params( + struct wiphy *wiphy, + u32 changed + ); + +int mtk_p2p_cfg80211_connect( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_connect_params *sme + ); + +int mtk_p2p_cfg80211_disconnect( + struct wiphy *wiphy, + struct net_device *dev, + u16 reason_code + ); + +int mtk_p2p_cfg80211_join_ibss( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params + ); + +int mtk_p2p_cfg80211_leave_ibss( + struct wiphy *wiphy, + struct net_device *dev + ); + +int mtk_p2p_cfg80211_set_txpower( + struct wiphy *wiphy, + enum nl80211_tx_power_setting type, + int mbm + ); + +int mtk_p2p_cfg80211_get_txpower( + struct wiphy *wiphy, + int *dbm + ); + +int mtk_p2p_cfg80211_set_power_mgmt( + struct wiphy *wiphy, + struct net_device *dev, + bool enabled, + int timeout + ); + +int +mtk_p2p_cfg80211_change_bss( + struct wiphy * wiphy, + struct net_device * dev, + struct bss_parameters * params + ); + +int +mtk_p2p_cfg80211_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 + ); + +int +mtk_p2p_cfg80211_cancel_remain_on_channel( + struct wiphy * wiphy, + struct net_device * dev, + u64 cookie + ); + +int +mtk_p2p_cfg80211_deauth( + struct wiphy * wiphy, + struct net_device * dev, + struct cfg80211_deauth_request * req +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) + , void *cookie +#endif + ); + + +int +mtk_p2p_cfg80211_disassoc( + struct wiphy * wiphy, + struct net_device * dev, + struct cfg80211_disassoc_request * req +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) + , void *cookie +#endif + ); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + +int +mtk_p2p_cfg80211_start_ap( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings + ); + + +int +mtk_p2p_cfg80211_change_beacon( + struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info + ); + +int +mtk_p2p_cfg80211_mgmt_tx( + struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, + bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); + +#else +int +mtk_p2p_cfg80211_add_set_beacon( + struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *info + ); + +int +mtk_p2p_cfg80211_mgmt_tx( + struct wiphy * wiphy, + struct net_device * dev, + struct ieee80211_channel * chan, + bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + unsigned int wait, + const u8 * buf, + size_t len, + u64 *cookie + ); + +#endif + + +int +mtk_p2p_cfg80211_stop_ap( + struct wiphy * wiphy, + struct net_device * dev + ); + + + +int +mtk_p2p_cfg80211_del_station( + struct wiphy * wiphy, + struct net_device * dev, + u8 * mac + ); + +int +mtk_p2p_cfg80211_set_channel( + IN struct wiphy * wiphy, + IN struct net_device * dev, + IN struct ieee80211_channel * chan, + IN enum nl80211_channel_type channel_type + ); + +int +mtk_p2p_cfg80211_set_bitrate_mask( + IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask + ); + + +void +mtk_p2p_cfg80211_mgmt_frame_register( + IN struct wiphy *wiphy, + IN struct net_device *dev, + IN u16 frame_type, + IN bool reg + ); + +#if CONFIG_NL80211_TESTMODE +int +mtk_p2p_cfg80211_testmode_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +int +mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +int +mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); + +#if CFG_SUPPORT_WFD +int +mtk_p2p_cfg80211_testmode_wfd_update_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +#endif + +int +mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + IN struct wiphy *wiphy, + IN void *data, + IN int len + ); +#else + #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" +#endif + +#endif + +/* I/O control handlers */ + +int +mtk_p2p_wext_get_priv ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_reconnect ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_auth ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_key ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_mlme_handler( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_powermode( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_get_powermode( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +/* Private Wireless I/O Controls takes use of iw_handler */ +int +mtk_p2p_wext_set_local_dev_info( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_provision_complete( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_start_stop_discovery( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_discovery_results( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_wsc_ie( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_connect_disconnect( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_password_ready( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_request_dev_info( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_invitation_indicate( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_invitation_status( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_pm_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_ps_profile ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_network_address ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_int ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ +int +mtk_p2p_wext_set_struct ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_get_struct ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ +int +mtk_p2p_wext_get_service_discovery_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_get_service_discovery_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_send_service_discovery_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_send_service_discovery_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_terminate_service_discovery_phase ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +#if CFG_SUPPORT_ANTI_PIRACY +int +mtk_p2p_wext_set_sec_check_request ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_get_sec_check_response ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); +#endif + +int +mtk_p2p_wext_set_noa_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_oppps_param ( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_set_p2p_version( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +int +mtk_p2p_wext_get_p2p_version( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + + +void +mtk_p2p_wext_set_Multicastlist( + IN P_GLUE_INFO_T prGlueInfo + ); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +int +mtk_p2p_wext_get_rssi( + IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, + IN OUT char *extra + ); + +struct iw_statistics * +mtk_p2p_wext_get_wireless_stats( + struct net_device *prDev + ); + +#endif + +int +mtk_p2p_wext_set_txpow( + IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, + IN OUT union iwreq_data *prTxPow, + IN char *pcExtra + ); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_P2P_IOCTL_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h new file mode 100755 index 000000000000..9a20c26b406f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,395 @@ +/* +** $Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_kal.h#2 $ +*/ + +/*! \file gl_p2p_kal.h + \brief Declaration of KAL functions for Wi-Fi Direct support + - kal*() which is provided by GLUE Layer. + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +/* +** $Log: gl_p2p_kal.h $ +** +** 08 29 2012 chinglan.wang +** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng] +** . + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 15 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Add group BSSID in invitation request indication. + * The BSSID is used for APP to decide the configure method. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 03 19 2011 terry.wu + * [WCXRP00000577] [MT6620 Wi-Fi][Driver][FW] Create V2.0 branch for firmware and driver + * create V2.0 p2p driver release based on label "MT6620_WIFI_P2P_DRIVER_V2_0_2100_0319_2011" from main trunk. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * +*/ + +#ifndef _GL_P2P_KAL_H +#define _GL_P2P_KAL_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "config.h" +#include "gl_typedef.h" +#include "gl_os.h" +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_p2p.h" +#include "gl_kal.h" +#include "gl_wext_priv.h" +#include "gl_p2p_ioctl.h" +#include "nic/p2p.h" + + +#if DBG + extern int allocatedMemSize; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* Service Discovery */ +VOID +kalP2PIndicateSDRequest( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucSeqNum + ); + +void +kalP2PIndicateSDResponse( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucSeqNum + ); + +VOID +kalP2PIndicateTXDone( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucSeqNum, + IN UINT_8 ucStatus + ); + +/*----------------------------------------------------------------------------*/ +/* Wi-Fi Direct handling */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T +kalP2PGetState ( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalP2PSetState ( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eState, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucRole + ); + +VOID +kalP2PUpdateAssocInfo( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, + IN BOOLEAN fgReassocRequest + ); + +UINT_32 +kalP2PGetFreqInKHz( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_8 +kalP2PGetRole( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalP2PSetRole( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, + IN PUINT_8 pucSSID, + IN UINT_8 ucSSIDLen, + IN UINT_8 ucRole + ); + +VOID +kalP2PSetCipher( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Cipher + ); + +BOOLEAN +kalP2PGetCipher( + IN P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +kalP2PGetTkipCipher( + IN P_GLUE_INFO_T prGlueInfo + ); + + +BOOLEAN +kalP2PGetCcmpCipher( + IN P_GLUE_INFO_T prGlueInfo + ); + + +VOID +kalP2PSetWscMode ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucWscMode + ); + +UINT_8 +kalP2PGetWscMode( + IN P_GLUE_INFO_T prGlueInfo + ); + +UINT_16 +kalP2PCalWSC_IELen( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType + ); + +VOID +kalP2PGenWSC_IE( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType, + IN PUINT_8 pucBuffer + ); + + +VOID +kalP2PUpdateWSC_IE( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucType, + IN PUINT_8 pucBuffer, + IN UINT_16 u2BufferLength + ); + + + +BOOLEAN +kalP2PIndicateFound( + IN P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalP2PIndicateConnReq( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucDevName, + IN INT_32 u4NameLength, + IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, + IN INT_32 i4ActiveConfigMethod + ); + +VOID +kalP2PInvitationStatus ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4InvStatus + ); + +VOID +kalP2PInvitationIndication( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, + IN UINT_8 ucInvitationType, + IN PUINT_8 pucGroupBssid + ); + + +struct net_device* +kalP2PGetDevHdlr( + P_GLUE_INFO_T prGlueInfo + ); + +VOID +kalGetChnlList( + IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, + IN PUINT_8 pucNumOfChannel, + IN P_RF_CHANNEL_INFO_T paucChannelList + ); + +#if CFG_SUPPORT_ANTI_PIRACY +VOID +kalP2PIndicateSecCheckRsp( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucRsp, + IN UINT_16 u2RspLen + ); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID +kalP2PIndicateChannelReady( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, + IN ENUM_CHNL_EXT_T eSco, + IN UINT_32 u4Duration + ); + +VOID +kalP2PIndicateScanDone( + IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgIsAbort + ); + +VOID +kalP2PIndicateBssInfo( + IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, + IN P_RF_CHANNEL_INFO_T prChannelInfo, + IN INT_32 i4SignalStrength + ); + +VOID +kalP2PIndicateRxMgmtFrame( + IN P_GLUE_INFO_T prGlueInfo, + IN P_SW_RFB_T prSwRfb + ); + +VOID +kalP2PIndicateMgmtTxStatus( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN BOOLEAN fgIsAck, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4FrameLen + ); + +VOID +kalP2PIndicateChannelExpired( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo + ); + +VOID +kalP2PGCIndicateConnectionStatus( + IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, + IN UINT_16 u2RxIELen, + IN UINT_16 u2StatusReason + ); + + +VOID +kalP2PGOStationUpdate( + IN P_GLUE_INFO_T prGlueInfo, + IN P_STA_RECORD_T prCliStaRec, + IN BOOLEAN fgIsNew + ); + +BOOLEAN +kalP2PSetBlackList ( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rbssid, + IN BOOLEAN fgIsblock + ); + +BOOLEAN +kalP2PCmpBlackList ( + IN P_GLUE_INFO_T prGlueInfo, + IN PARAM_MAC_ADDRESS rbssid + ); + +VOID +kalP2PSetMaxClients ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4MaxClient + ); + +BOOLEAN +kalP2PMaxClients ( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4NumClient + ); + +#endif /* _GL_P2P_KAL_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h new file mode 100755 index 000000000000..e2232499608a --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h @@ -0,0 +1,199 @@ +/* +** $Id: +//Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/os/linux/include/gl_p2p_os.h#28 $ +*/ + +/*! \file gl_p2p_os.h + \brief List the external reference to OS for p2p GLUE Layer. + + In this file we define the data structure - GLUE_INFO_T to store those objects + we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the + external reference (header file, extern func() ..) to OS for GLUE Layer should + also list down here. +*/ + + + + + +#ifndef _GL_P2P_OS_H +#define _GL_P2P_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +struct _GL_P2P_INFO_T { + + /* Device handle */ + struct net_device *prDevHandler; + + #if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev wdev; + + struct cfg80211_scan_request *prScanRequest; + + UINT_64 u8Cookie; + + /* Generation for station list update. */ + INT_32 i4Generation; + + UINT_32 u4OsMgmtFrameFilter; + + #endif + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* glue layer variables */ + /*move to glueinfo->adapter*/ + // BOOLEAN fgIsRegistered; + UINT_32 u4FreqInKHz; /* frequency */ + UINT_8 ucRole; /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + UINT_8 ucIntent; /* range: 0-15 */ + UINT_8 ucScanMode; /* 0: Search & Listen, 1: Scan without probe response */ + + ENUM_PARAM_MEDIA_STATE_T eState; + UINT_32 u4PacketFilter; + PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR]; + + /* connection-requested peer information */ + UINT_8 aucConnReqDevName[32]; + INT_32 u4ConnReqNameLength; + PARAM_MAC_ADDRESS rConnReqPeerAddr; + PARAM_MAC_ADDRESS rConnReqGroupAddr; /* For invitation group. */ + UINT_8 ucConnReqDevType; + INT_32 i4ConnReqConfigMethod; + INT_32 i4ConnReqActiveConfigMethod; + + UINT_32 u4CipherPairwise; + UINT_8 ucWSCRunning; + + UINT_8 aucWSCIE[3][400]; /* 0 for beacon, 1 for probe req, 2 for probe response */ + UINT_16 u2WSCIELen[3]; + +#if CFG_SUPPORT_WFD + UINT_8 aucVenderIE[1024]; /* Save the other IE for prove resp */ + UINT_16 u2VenderIELen; +#endif + + UINT_8 ucOperatingChnl; + UINT_8 ucInvitationType; + + UINT_32 u4InvStatus; + + /* For SET_STRUCT/GET_STRUCT */ + UINT_8 aucOidBuf[4096]; + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + UINT_8 aucSecCheck[256]; + UINT_8 aucSecCheckRsp[256]; +#endif + + /* Hotspot Client Management */ + PARAM_MAC_ADDRESS aucblackMACList[8]; + UINT_8 ucMaxClients; + +}; + + +BOOLEAN +p2pRegisterToWlan( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +p2pUnregisterToWlan( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +p2pLaunch( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +p2pRemove( + P_GLUE_INFO_T prGlueInfo + ); + +VOID +p2pSetMode( + IN BOOLEAN fgIsAPMOde + ); + + +BOOLEAN +glRegisterP2P( + P_GLUE_INFO_T prGlueInfo, + const char *prDevName, + BOOLEAN fgIsApMode + ); + +BOOLEAN +glUnregisterP2P( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +p2pNetRegister( + P_GLUE_INFO_T prGlueInfo, + BOOLEAN fgIsRtnlLockAcquired + ); + +BOOLEAN +p2pNetUnregister( + P_GLUE_INFO_T prGlueInfo, + BOOLEAN fgIsRtnlLockAcquired + ); + +BOOLEAN +p2pStopImmediate( + P_GLUE_INFO_T prGlueInfo + ); + +BOOLEAN +p2PFreeInfo( + P_GLUE_INFO_T prGlueInfo + ); + + +#endif diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h new file mode 100755 index 000000000000..b85978a80e76 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h @@ -0,0 +1,131 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_rst.h#1 $ +*/ + +/*! \file gl_rst.h + \brief Declaration of functions and finite state machine for + MT6620 Whole-Chip Reset Mechanism +*/ + + + + +#ifndef _GL_RST_H +#define _GL_RST_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* duplicated from wmt_exp.h for better driver isolation */ +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_STP = 5, + WMTDRV_TYPE_SDIO1 = 6, + WMTDRV_TYPE_SDIO2 = 7, + WMTDRV_TYPE_LPBK = 8, + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY= 3, + WMTMSG_TYPE_HW_FUNC_ON= 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + +typedef enum _ENUM_WMTRSTMSG_TYPE_T{ + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; + +typedef void (*PF_WMT_CB)( + ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + void *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client + can't touch this buffer after this function return. */ + unsigned int /* Buffer size in unit of byte */ + ); + + +typedef enum _ENUM_WIFI_NETLINK_GRP_T{ + WIFI_NETLINK_GRP_RESET, + WIFI_NETLINK_GRP_MAX +} ENUM_WIFI_NETLINK_GRP_T, *P_ENUM_WIFI_NETLINK_GRP_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/* Reset Initialization/Uninitialization */ +/*----------------------------------------------------------------------------*/ +VOID +glResetInit( + VOID + ); + +VOID +glResetUninit( + VOID + ); + +VOID +glSendResetRequest( + VOID + ); + +BOOLEAN +kalIsResetting( + VOID + ); + + +#endif /* _GL_RST_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h new file mode 100755 index 000000000000..16f0af93be89 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h @@ -0,0 +1,24 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_sec.h#1 $ +*/ + +/*! \file p2p_fsm.h + \brief Declaration of functions and finite state machine for P2P Module. + + Declaration of functions and finite state machine for P2P Module. +*/ + + + + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h new file mode 100755 index 000000000000..e220b43c36ca --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h @@ -0,0 +1,279 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_typedef.h#1 $ +*/ + +/*! \file gl_typedef.h + \brief Definition of basic data type(os dependent). + + In this file we define the basic data type. +*/ + + + +/* +** $Log: gl_typedef.h $ + * + * 06 22 2012 cp.wu + * [WCXRP00001257] [MT6620][MT5931][MT6628][Driver][Linux] Modify KAL_HZ to align ms accuracy + * modify KAL_HZ to (1000) for correct definition. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\6 2009-08-18 22:57:14 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\5 2008-09-22 23:19:30 GMT mtk01461 +** Update comment for code review +** \main\maintrunk.MT5921\4 2008-09-05 17:25:16 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\3 2007-11-09 11:00:50 GMT mtk01425 +** 1. Use macro to unify network-to-host and host-to-network related functions +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +#if defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define HZ of timer tick for function kalGetTimeTick() */ +#define KAL_HZ (1000) + +/* Miscellaneous Equates */ +#ifndef FALSE + #define FALSE ((BOOL) 0) + #define TRUE ((BOOL) 1) +#endif /* FALSE */ + +#ifndef NULL + #if defined(__cplusplus) + #define NULL 0 + #else + #define NULL ((void *) 0) + #endif +#endif + +#if defined(CONFIG_HAS_EARLYSUSPEND) +typedef void (*early_suspend_callback)(struct early_suspend *h); +typedef void (*late_resume_callback) (struct early_suspend *h); +#endif + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for void */ +typedef void VOID, *PVOID, **PPVOID; + +/* Type definition for Boolean */ +typedef unsigned char BOOL, *PBOOL, BOOLEAN, *PBOOLEAN; + +/* Type definition for signed integers */ +typedef signed char CHAR, *PCHAR, **PPCHAR; +typedef signed char INT_8, *PINT_8, **PPINT_8; +typedef signed short INT_16, *PINT_16, **PPINT_16; +typedef signed long INT_32, *PINT_32, **PPINT_32; +typedef signed long long INT_64, *PINT_64, **PPINT_64; + +/* Type definition for unsigned integers */ +typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; +typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; +typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; +typedef unsigned long ULONG, UINT_32, *PUINT_32, **PPUINT_32; +typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; + +typedef unsigned long OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME; + + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +typedef union _LARGE_INTEGER { + struct { + UINT_32 LowPart; + INT_32 HighPart; + } u; + INT_64 QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + UINT_32 LowPart; + UINT_32 HighPart; + } u; + UINT_64 QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + + +typedef INT_32 (*probe_card)(PVOID pvData); +typedef VOID (*remove_card)(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define IN //volatile +#define OUT //volatile + +#define __KAL_INLINE__ static __inline__ +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __attribute__ ((aligned (4))) + + +#ifndef BIT +#define BIT(n) ((UINT_32) 1UL << (n)) +#endif /* BIT */ + +#ifndef BITS +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + + +/* This macro returns the byte offset of a named field in a known structure + type. + _type - structure name, + _field - field name of the structure */ +#ifndef OFFSET_OF + #define OFFSET_OF(_type, _field) ((UINT_32)&(((_type *)0)->_field)) +#endif /* OFFSET_OF */ + + +/* This macro returns the base address of an instance of a structure + * given the type of the structure and the address of a field within the + * containing structure. + * _addrOfField - address of current field of the structure, + * _type - structure name, + * _field - field name of the structure + */ +#ifndef ENTRY_OF + #define ENTRY_OF(_addrOfField, _type, _field) \ + ((_type *)((PINT_8)(_addrOfField) - (PINT_8)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + + +/* This macro align the input value to the DW boundary. + * _value - value need to check + */ +#ifndef ALIGN_4 + #define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 + #define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 + #define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD + #define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE + #define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 // Little-Endian + #define CONST_NTOHS(_x) __constant_ntohs(_x) + + #define CONST_HTONS(_x) __constant_htons(_x) + + #define NTOHS(_x) ntohs(_x) + + #define HTONS(_x) htons(_x) + + #define NTOHL(_x) ntohl(_x) + + #define HTONL(_x) htonl(_x) + +#else // Big-Endian + + #define CONST_NTOHS(_x) + + #define CONST_HTONS(_x) + + #define NTOHS(_x) + + #define HTONS(_x) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_TYPEDEF_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h new file mode 100755 index 000000000000..7a5129f7a54d --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h @@ -0,0 +1,376 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext.h#1 $ +*/ + +/*! \file gl_wext.h + \brief This file is for Portable Driver linux wireless extension support. +*/ + + + +/* +** $Log: gl_wext.h $ + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. . + * + * 09 27 2010 wh.su + * NULL + * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\12 2009-10-20 17:38:33 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw. +** \main\maintrunk.MT5921\11 2009-09-28 20:19:28 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\10 2009-09-03 12:12:35 GMT mtk01088 +** adding the function declaration +** \main\maintrunk.MT5921\9 2009-08-18 22:57:17 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\8 2008-08-29 16:59:07 GMT mtk01088 +** fixed compiling error +** \main\maintrunk.MT5921\7 2008-08-29 14:13:28 GMT mtk01088 +** adjust the header file for code refine +** \main\maintrunk.MT5921\6 2008-03-28 10:40:31 GMT mtk01461 +** Add set desired rate in Linux STD IOCTL +** \main\maintrunk.MT5921\5 2008-03-11 14:51:08 GMT mtk01461 +** Refine private IOCTL functions +** \main\maintrunk.MT5921\4 2008-02-12 23:45:45 GMT mtk01461 +** Add Set Frequency & Channel oid support for Linux +** \main\maintrunk.MT5921\3 2007-11-06 19:36:19 GMT mtk01088 +** add the WPS related code +*/ + +#ifndef _GL_WEXT_H +#define _GL_WEXT_H + +#ifdef WIRELESS_EXT +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define KILO 1000 +#define RATE_5_5M 11 /* 5.5M */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PARAM_FIXED_IEs { + UINT_8 aucTimestamp[8]; + UINT_16 u2BeaconInterval; + UINT_16 u2Capabilities; +} PARAM_FIXED_IEs; + +typedef struct _PARAM_VARIABLE_IE_T { + UINT_8 ucElementID; + UINT_8 ucLength; + UINT_8 aucData[1]; +} PARAM_VARIABLE_IE_T, *P_PARAM_VARIABLE_IE_T; + + +#if WIRELESS_EXT < 18 + +#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses struct iw_mlme */ +/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ +#define IW_MLME_DEAUTH 0 +#define IW_MLME_DISASSOC 1 + +/*! \brief SIOCSIWMLME data */ +struct iw_mlme { + __u16 cmd; /*!< IW_MLME_* */ + __u16 reason_code; + struct sockaddr addr; +}; + +#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ +#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ +/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ +#define IW_AUTH_INDEX 0x0FFF +#define IW_AUTH_FLAGS 0xF000 +/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) + * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the + * parameter that is being set/get to; value will be read/written to + * struct iw_param value field) */ +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 +#if CFG_SUPPORT_802_11W +#define IW_AUTH_MFP 12 + +#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ +#endif + +/* IW_AUTH_WPA_VERSION values (bit field) */ +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 + +/* IW_AUTH_KEY_MGMT values (bit field) */ +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 +#define IW_AUTH_KEY_MGMT_WPA_NONE 4 + +/* IW_AUTH_80211_AUTH_ALG values (bit field) */ +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +/* IW_AUTH_ROAMING_CONTROL values */ +#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ +#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming + * control */ + +#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ +#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_SEQ_MAX_SIZE 8 +/* struct iw_encode_ext ->alg */ +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 +#if CFG_SUPPORT_802_11W +#define IW_ENCODE_ALG_AES_CMAC 5 +#endif + +/* struct iw_encode_ext ->ext_flags */ +#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 +#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 +#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 +#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 + +struct iw_encode_ext { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + struct sockaddr addr; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[0]; +}; + +#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ +#define IW_PMKSA_ADD 1 +#define IW_PMKSA_REMOVE 2 +#define IW_PMKSA_FLUSH 3 + +#define IW_PMKID_LEN 16 + +struct iw_pmksa { + __u32 cmd; /*!< IW_PMKSA_* */ + struct sockaddr bssid; + __u8 pmkid[IW_PMKID_LEN]; +}; + +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) */ + +#endif /* WIRELESS_EXT < 18 */ + +#if WIRELESS_EXT < 17 +/* Statistics flags (bitmask in updated) */ +#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#endif + +enum { + IEEE80211_FILTER_TYPE_BEACON = 1<<0, + IEEE80211_FILTER_TYPE_PROBE_REQ = 1<<1, + IEEE80211_FILTER_TYPE_PROBE_RESP = 1<<2, + IEEE80211_FILTER_TYPE_ASSOC_REQ = 1<<3, + IEEE80211_FILTER_TYPE_ASSOC_RESP = 1<<4, + IEEE80211_FILTER_TYPE_AUTH = 1<<5, + IEEE80211_FILTER_TYPE_DEAUTH = 1<<6, + IEEE80211_FILTER_TYPE_DISASSOC = 1<<7, + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ +}; + +#if CFG_SUPPORT_WAPI +#define IW_AUTH_WAPI_ENABLED 0x20 +#define IW_ENCODE_ALG_SMS4 0x20 +#endif + +#if CFG_SUPPORT_WAPI /* Android+ */ +#define IW_AUTH_KEY_MGMT_WAPI_PSK 3 +#define IW_AUTH_KEY_MGMT_WAPI_CERT 4 +#endif +#define IW_AUTH_KEY_MGMT_WPS 5 + +#if CFG_SUPPORT_802_11W +#define IW_AUTH_KEY_MGMT_802_1X_SHA256 7 +#define IW_AUTH_KEY_MGMT_PSK_SHA256 8 +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern const struct iw_handler_def wext_handler_def; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* wireless extensions' ioctls */ +int +wext_support_ioctl( + IN struct net_device *prDev, + IN struct ifreq *prIfReq, + IN int i4Cmd + ); + +int +wext_set_rate ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN struct iw_param *prRate, + IN char *pcExtra + ); + +void +wext_indicate_wext_event( + IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, + IN unsigned char *pucData, + IN unsigned int u4DataLen + ); + +struct iw_statistics * +wext_get_wireless_stats ( + struct net_device *prDev + ); + +int +wext_get_priv ( + IN struct net_device *prNetDev, + IN struct ifreq *prIfReq + ); + +BOOLEAN +wextSrchDesiredWPAIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); + +#if CFG_SUPPORT_WPS +BOOLEAN +wextSrchDesiredWPSIE ( + IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, + IN UINT_8 ucDesiredElemId, + OUT PUINT_8 *ppucDesiredIE + ); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h new file mode 100755 index 000000000000..4a40ce491bae --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h @@ -0,0 +1,396 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext_priv.h#3 $ +*/ + +/*! \file gl_wext_priv.h + \brief This file includes private ioctl support. +*/ + + + +/* +** $Log: gl_wext_priv.h $ + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check. + * Add a CMD ID for P2P driver version query. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\16 2009-09-29 16:47:23 GMT mtk01090 +** Remove unused functions +** \main\maintrunk.MT5921\15 2009-09-28 20:19:31 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\14 2009-05-07 22:26:06 GMT mtk01089 +** add private IO control for Linux BWCS +** \main\maintrunk.MT5921\13 2008-08-29 14:55:20 GMT mtk01088 +** adjust the code to meet coding style +** \main\maintrunk.MT5921\12 2008-07-16 15:23:45 GMT mtk01104 +** Support GPIO2 mode +** \main\maintrunk.MT5921\11 2008-07-14 13:55:58 GMT mtk01104 +** Support PRIV_CMD_BT_COEXIST +** \main\maintrunk.MT5921\10 2008-07-09 00:20:24 GMT mtk01461 +** Add priv oid to support WMM_PS_TEST +** \main\maintrunk.MT5921\9 2008-05-30 20:27:24 GMT mtk01461 +** Add POWER_MODE Private IOCTL cmd +** \main\maintrunk.MT5921\8 2008-04-17 23:06:44 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\7 2008-03-31 21:01:24 GMT mtk01461 +** Add priv IOCTL for VOIP settings +** \main\maintrunk.MT5921\6 2008-03-31 13:49:47 GMT mtk01461 +** add priv ioctl arg definition for turning on / off roaming +** \main\maintrunk.MT5921\5 2008-03-26 15:35:09 GMT mtk01461 +** Add CSUM offload priv ioctl for Linux +** \main\maintrunk.MT5921\4 2008-03-11 14:51:11 GMT mtk01461 +** Refine private IOCTL functions +** \main\maintrunk.MT5921\3 2007-11-06 19:36:25 GMT mtk01088 +** add the WPS related code +*/ + +#ifndef _GL_WEXT_PRIV_H +#define _GL_WEXT_PRIV_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +/* If it is set to 1, iwpriv will support register read/write */ +#define CFG_SUPPORT_PRIV_MCR_RW 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* New wireless extensions API - SET/GET convention (even ioctl numbers are + * root only) + */ +#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) +#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) + +#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) +#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) +#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) +#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) +#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) +#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) +#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) +#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) + +#define PRIV_CMD_REG_DOMAIN 0 +#define PRIV_CMD_BEACON_PERIOD 1 +#define PRIV_CMD_ADHOC_MODE 2 + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + #define PRIV_CMD_CSUM_OFFLOAD 3 +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +#define PRIV_CMD_ROAMING 4 +#define PRIV_CMD_VOIP_DELAY 5 +#define PRIV_CMD_POWER_MODE 6 + +#define PRIV_CMD_WMM_PS 7 +#define PRIV_CMD_BT_COEXIST 8 +#define PRIV_GPIO2_MODE 9 + +#define PRIV_CUSTOM_SET_PTA 10 +#define PRIV_CUSTOM_CONTINUOUS_POLL 11 +#define PRIV_CUSTOM_SINGLE_ANTENNA 12 +#define PRIV_CUSTOM_BWCS_CMD 13 +#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION 14//later +#define PRIV_CMD_OID 15 +#define PRIV_SEC_MSG_OID 16 + +#define PRIV_CMD_TEST_MODE 17 +#define PRIV_CMD_TEST_CMD 18 +#define PRIV_CMD_ACCESS_MCR 19 +#define PRIV_CMD_SW_CTRL 20 + +#if 1 /* ANTI_PRIVCY */ +#define PRIV_SEC_CHECK_OID 21 +#endif + +#define PRIV_CMD_WSC_PROBE_REQ 22 + +#define PRIV_CMD_P2P_VERSION 23 + +#define PRIV_CMD_GET_CH_LIST 24 + +#define PRIV_CMD_SET_TX_POWER 25 + +#define PRIV_CMD_BAND_CONFIG 26 + +#define PRIV_CMD_DUMP_MEM 27 + +#define PRIV_CMD_P2P_MODE 28 + +/* 802.3 Objects (Ethernet) */ +#define OID_802_3_CURRENT_ADDRESS 0x01010102 + +/* IEEE 802.11 OIDs */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E +#define OID_802_11_CONFIGURATION 0x0D010211 + +/* PnP and PM OIDs, NDIS default OIDS */ +#define OID_PNP_SET_POWER 0xFD010101 + +#define OID_CUSTOM_OID_INTERFACE_VERSION 0xFFA0C000 + +/* MT5921 specific OIDs */ +#define OID_CUSTOM_BT_COEXIST_CTRL 0xFFA0C580 +#define OID_CUSTOM_POWER_MANAGEMENT_PROFILE 0xFFA0C581 +#define OID_CUSTOM_PATTERN_CONFIG 0xFFA0C582 +#define OID_CUSTOM_BG_SSID_SEARCH_CONFIG 0xFFA0C583 +#define OID_CUSTOM_VOIP_SETUP 0xFFA0C584 +#define OID_CUSTOM_ADD_TS 0xFFA0C585 +#define OID_CUSTOM_DEL_TS 0xFFA0C586 +#define OID_CUSTOM_SLT 0xFFA0C587 +#define OID_CUSTOM_ROAMING_EN 0xFFA0C588 +#define OID_CUSTOM_WMM_PS_TEST 0xFFA0C589 +#define OID_CUSTOM_COUNTRY_STRING 0xFFA0C58A +#define OID_CUSTOM_MULTI_DOMAIN_CAPABILITY 0xFFA0C58B +#define OID_CUSTOM_GPIO2_MODE 0xFFA0C58C +#define OID_CUSTOM_CONTINUOUS_POLL 0xFFA0C58D +#define OID_CUSTOM_DISABLE_BEACON_DETECTION 0xFFA0C58E + +/* CR1460, WPS privacy bit check disable */ +#define OID_CUSTOM_DISABLE_PRIVACY_CHECK 0xFFA0C600 + +/* Precedent OIDs */ +#define OID_CUSTOM_MCR_RW 0xFFA0C801 +#define OID_CUSTOM_EEPROM_RW 0xFFA0C803 +#define OID_CUSTOM_SW_CTRL 0xFFA0C805 +#define OID_CUSTOM_MEM_DUMP 0xFFA0C807 + + +/* RF Test specific OIDs */ +#define OID_CUSTOM_TEST_MODE 0xFFA0C901 +#define OID_CUSTOM_TEST_RX_STATUS 0xFFA0C903 +#define OID_CUSTOM_TEST_TX_STATUS 0xFFA0C905 +#define OID_CUSTOM_ABORT_TEST_MODE 0xFFA0C906 +#define OID_CUSTOM_MTK_WIFI_TEST 0xFFA0C911 + +/* BWCS */ +#define OID_CUSTOM_BWCS_CMD 0xFFA0C931 +#define OID_CUSTOM_SINGLE_ANTENNA 0xFFA0C932 +#define OID_CUSTOM_SET_PTA 0xFFA0C933 + +/* NVRAM */ +#define OID_CUSTOM_MTK_NVRAM_RW 0xFFA0C941 +#define OID_CUSTOM_CFG_SRC_TYPE 0xFFA0C942 +#define OID_CUSTOM_EEPROM_TYPE 0xFFA0C943 + + +#if CFG_SUPPORT_WAPI +#define OID_802_11_WAPI_MODE 0xFFA0CA00 +#define OID_802_11_WAPI_ASSOC_INFO 0xFFA0CA01 +#define OID_802_11_SET_WAPI_KEY 0xFFA0CA02 +#endif + +#if CFG_SUPPORT_WPS2 +#define OID_802_11_WSC_ASSOC_INFO 0xFFA0CB00 +#endif + + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* NIC BBCR configuration entry structure */ +typedef struct _PRIV_CONFIG_ENTRY { + UINT_8 ucOffset; + UINT_8 ucValue; +} PRIV_CONFIG_ENTRY, *PPRIV_CONFIG_ENTRY; + +typedef WLAN_STATUS (*PFN_OID_HANDLER_FUNC_REQ) ( + IN PVOID prAdapter, + IN OUT PVOID pvBuf, + IN UINT_32 u4BufLen, + OUT PUINT_32 pu4OutInfoLen + ); + +typedef enum _ENUM_OID_METHOD_T { + ENUM_OID_GLUE_ONLY, + ENUM_OID_GLUE_EXTENSION, + ENUM_OID_DRIVER_CORE +} ENUM_OID_METHOD_T, *P_ENUM_OID_METHOD_T; + +/* OID set/query processing entry */ +typedef struct _WLAN_REQ_ENTRY { + UINT_32 rOid; /* OID */ + PUINT_8 pucOidName; /* OID name text */ + BOOLEAN fgQryBufLenChecking; + BOOLEAN fgSetBufLenChecking; + ENUM_OID_METHOD_T eOidMethod; + UINT_32 u4InfoBufLen; + PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC*/ + PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ +} WLAN_REQ_ENTRY, *P_WLAN_REQ_ENTRY; + +typedef struct _NDIS_TRANSPORT_STRUCT { + UINT_32 ndisOidCmd; + UINT_32 inNdisOidlength; + UINT_32 outNdisOidLength; + UINT_8 ndisOidContent[16]; +} NDIS_TRANSPORT_STRUCT, *P_NDIS_TRANSPORT_STRUCT; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int +priv_set_int( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ); + +int +priv_get_int( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ); + +int +priv_set_ints( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ); + +int +priv_get_ints( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ); + +int +priv_set_struct( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra + ); + +int +priv_get_struct ( + IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra + ); + +int +priv_support_ioctl ( + IN struct net_device *prDev, + IN OUT struct ifreq *prReq, + IN int i4Cmd + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_WEXT_PRIV_H */ + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c new file mode 100755 index 000000000000..9eecea20333f --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c @@ -0,0 +1,620 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $ +*/ + +/*! \file "platform.c" + \brief This file including the protocol layer privacy function. + + This file provided the macros and functions library support for the + protocol layer security setting from wlan_oid.c and for parse.c and + rsn.c and nic_privacy.c + +*/ + + + +/* +** $Log: platform.c $ + * + * 11 14 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 09 13 2011 jeffrey.chang + * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection + * fix the pointer casting + * + * 06 29 2011 george.huang + * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 + * . + * + * 06 28 2011 george.huang + * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 + * remove un-used code + * + * 05 11 2011 jeffrey.chang + * NULL + * fix build error + * + * 05 09 2011 jeffrey.chang + * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change + * support ARP filter through kernel notifier + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 18 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * remove early suspend functions + * + * 03 03 2011 jeffrey.chang + * NULL + * add the ARP filter callback + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 02 01 2011 cp.wu + * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 branch + * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/... + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * +** +*/ +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12) + #include +#endif + +#include "gl_os.h" + +#ifndef CONFIG_X86 +#if defined(CONFIG_HAS_EARLY_SUSPEND) + #include +#endif +#endif + + +extern BOOLEAN fgIsUnderEarlierSuspend; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define WIFI_NVRAM_FILE_NAME "/data/nvram/APCFG/APRDEB/WIFI" +#define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + +static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +//#ifdef CONFIG_IPV6 +#if 0 + UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack + UINT_32 u4NumIPv6 = 0; +#endif + struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n")); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, ("netdev_event: xxx\n")); + return NOTIFY_DONE; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n")); + return NOTIFY_DONE; + } + ASSERT(prGlueInfo); + + if (fgIsUnderEarlierSuspend == false) { + DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated)); + return NOTIFY_DONE; + } + + + + // <3> get the IPv4 address + if(!prDev || !(prDev->ip_ptr)||\ + !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ + DBGLOG(REQ, INFO, ("ip is not avaliable.\n")); + return NOTIFY_DONE; + } + + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n", + ip[0],ip[1],ip[2],ip[3])); + + // todo: traverse between list to find whole sets of IPv4 addresses + if (!((ip[0] == 0) && + (ip[1] == 0) && + (ip[2] == 0) && + (ip[3] == 0))) { + u4NumIPv4++; + } + +//#ifdef CONFIG_IPV6 +#if 0 + if(!prDev || !(prDev->ip6_ptr)||\ + !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ + printk(KERN_INFO "ipv6 is not avaliable.\n"); + return NOTIFY_DONE; + } + + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0],ip6[1],ip6[2],ip6[3], + ip6[4],ip6[5],ip6[6],ip6[7], + ip6[8],ip6[9],ip6[10],ip6[11], + ip6[12],ip6[13],ip6[14],ip6[15] + ); + + // todo: traverse between list to find whole sets of IPv6 addresses + if (!((ip6[0] == 0) && + (ip6[1] == 0) && + (ip6[2] == 0) && + (ip6[3] == 0) && + (ip6[4] == 0) && + (ip6[5] == 0))) { + //u4NumIPv6++; + } +#endif + + // here we can compare the dev with other network's netdev to + // set the proper arp filter + // + // IMPORTANT: please make sure if the context can sleep, if the context can't sleep + // we should schedule a kernel thread to do this for us + + // <7> set up the ARP filter + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_8 aucBuf[32] = {0}; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + +//#ifdef CONFIG_IPV6 +#if 0 + prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; +#else + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#endif + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); +#endif + } +//#ifdef CONFIG_IPV6 +#if 0 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6;; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(aucBuf)); + + DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID)prParamNetAddrList, + u4Len, + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus)); + } + } + + return NOTIFY_DONE; + +} + +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; + +void wlanRegisterNotifier(void) +{ + register_inetaddr_notifier(&inetaddr_notifier); +} + +//EXPORT_SYMBOL(wlanRegisterNotifier); + +void wlanUnregisterNotifier(void) +{ + unregister_inetaddr_notifier(&inetaddr_notifier); +} + +//EXPORT_SYMBOL(wlanUnregisterNotifier); + +#ifndef CONFIG_X86 +#if defined(CONFIG_HAS_EARLYSUSPEND) + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register platform driver to os +* +* \param[in] wlanSuspend Function pointer to platform suspend function +* \param[in] wlanResume Function pointer to platform resume function +* +* \return The result of registering earlysuspend +*/ +/*----------------------------------------------------------------------------*/ + +int glRegisterEarlySuspend( + struct early_suspend *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume) +{ + int ret = 0; + + if(NULL != wlanSuspend) + prDesc->suspend = wlanSuspend; + else{ + DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n")); + ret = -1; + } + + if(NULL != wlanResume) + prDesc->resume = wlanResume; + else{ + DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n")); + ret = -1; + } + + register_early_suspend(prDesc); + return ret; +} + +//EXPORT_SYMBOL(glRegisterEarlySuspend); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will un-register platform driver to os +* +* \return The result of un-registering earlysuspend +*/ +/*----------------------------------------------------------------------------*/ + +int glUnregisterEarlySuspend(struct early_suspend *prDesc) +{ + int ret = 0; + + unregister_early_suspend(prDesc); + + prDesc->suspend = NULL; + prDesc->resume = NULL; + + return ret; +} + +//EXPORT_SYMBOL(glUnregisterEarlySuspend); +#endif +#endif // !CONFIG_X86 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Utility function for reading data from files on NVRAM-FS +* +* \param[in] +* filename +* len +* offset +* \param[out] +* buf +* \return +* actual length of data being read +*/ +/*----------------------------------------------------------------------------*/ +static int +nvram_read( + char *filename, + char *buf, + ssize_t len, + int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + fd = filp_open(filename, O_RDONLY, 0644); + + if(IS_ERR(fd)) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n")); + return -1; + } + + do { + if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n")); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if(fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to seek!!\n")); + break; + } + } + else { + fd->f_pos = offset; + } + } + + retLen = fd->f_op->read(fd, + buf, + len, + &fd->f_pos); + + } while(FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else // !CFG_SUPPORT_NVRAM + + return -EIO; + +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Utility function for writing data to files on NVRAM-FS +* +* \param[in] +* filename +* buf +* len +* offset +* \return +* actual length of data being written +*/ +/*----------------------------------------------------------------------------*/ +static int +nvram_write ( + char *filename, + char *buf, + ssize_t len, + int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + fd = filp_open(filename, O_WRONLY|O_CREAT, 0644); + + if(IS_ERR(fd)) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n")); + return -1; + } + + do{ + if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n")); + break; + } /* End of if */ + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if(fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to seek!!\n")); + break; + } + } + else { + fd->f_pos = offset; + } + } + + retLen = fd->f_op->write(fd, + buf, + len, + &fd->f_pos); + + } while(FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else // !CFG_SUPPORT_NVRAMS + + return -EIO; + +#endif +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief API for reading data on NVRAM +* +* \param[in] +* prGlueInfo +* u4Offset +* \param[out] +* pu2Data +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalCfgDataRead16( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4Offset, + OUT PUINT_16 pu2Data + ) +{ + if(pu2Data == NULL) { + return FALSE; + } + + if(nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, + sizeof(unsigned short), + u4Offset) != sizeof(unsigned short)) { + return FALSE; + } + else { + return TRUE; + } +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief API for writing data on NVRAM +* +* \param[in] +* prGlueInfo +* u4Offset +* u2Data +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalCfgDataWrite16( + IN P_GLUE_INFO_T prGlueInfo, + UINT_32 u4Offset, + UINT_16 u2Data + ) +{ + if(nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, + sizeof(unsigned short), + u4Offset) != sizeof(unsigned short)) { + return FALSE; + } + else { + return TRUE; + } +} + + diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h new file mode 100755 index 000000000000..716a0628d755 --- /dev/null +++ b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h @@ -0,0 +1,200 @@ +/* +** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 $ +*/ + +/*! \file "version.h" + \brief Driver's version definition + +*/ + + + +/* +** $Log: version.h $ + * + * 11 01 2011 chinglan.wang + * NULL + * Change the version number to v2.0.1.1. + * + * 08 26 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.9.. + * + * 08 23 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.8. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * correct typo. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * for building MT6628 Win32 driver environment + * + * 08 03 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.7. + * + * 07 24 2011 puff.wen + * NULL + * [MT5931][Beta 5]Change the version number to v0.2.2.0 + * + * 06 01 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.6.. + * + * 05 09 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.5.. + * + * 04 19 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.4. + * + * 04 18 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.3. + * + * 03 25 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.2. + * + * 03 21 2011 chinglan.wang + * NULL + * Change the version number to 2.0.0.1. + * + * 03 18 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.0. + * + * 02 11 2011 chinglan.wang + * NULL + * Change to the version 1.2.0.2. + * + * 02 10 2011 chinglan.wang + * NULL + * Change the version to 1.2.0.1. + * + * 02 08 2011 cp.wu + * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number + * change version number to v1.2.0.0 for preparing v1.2 software package release. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * [WINDDK] build system changes for MT5931 + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-12-14 14:10:55 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-17 22:41:00 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-13 16:20:33 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:27:13 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _VERSION_H +#define _VERSION_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef NIC_AUTHOR +#define NIC_AUTHOR "NIC_AUTHOR" +#endif +#ifndef NIC_DESC +#define NIC_DESC "NIC_DESC" +#endif + +#ifndef NIC_NAME + #if defined(MT6620) + #define NIC_NAME "MT6620" + #define NIC_DEVICE_ID "MT6620" + #define NIC_DEVICE_ID_LOW "mt6620" + #elif defined(MT5931) + #define NIC_NAME "MT5931" + #define NIC_DEVICE_ID "MT5931" + #define NIC_DEVICE_ID_LOW "mt5931" + #elif defined(MT6628) + #define NIC_NAME "MT6628" + #define NIC_DEVICE_ID "MT6628" + #define NIC_DEVICE_ID_LOW "mt6628" + #endif +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#if defined(MT6620) + #define NIC_PRODUCT_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter" + #define NIC_DRIVER_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter Driver" +#elif defined(MT5931) + #define NIC_PRODUCT_NAME "MediaTek Inc. MT5931 Wireless LAN Adapter" + #define NIC_DRIVER_NAME "MediaTek Inc. MT5931 Wireless LAN Adapter Driver" +#elif defined(MT6628) + #define NIC_PRODUCT_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter" + #define NIC_DRIVER_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter Driver" +#endif + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 2 +#define NIC_DRIVER_MINOR_VERSION 0 +#define NIC_DRIVER_VERSION 2,0,1,1 +#define NIC_DRIVER_VERSION_STRING "2.0.1.1" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +#endif /* _VERSION_H */ + diff --git a/drivers/mtk_wcn_combo/gps/Makefile b/drivers/mtk_wcn_combo/gps/Makefile new file mode 100755 index 000000000000..db3b2a544d88 --- /dev/null +++ b/drivers/mtk_wcn_combo/gps/Makefile @@ -0,0 +1,49 @@ +# Copyright Statement: +# +# This software/firmware and related documentation ("MediaTek Software") are +# protected under relevant copyright laws. The information contained herein +# is confidential and proprietary to MediaTek Inc. and/or its licensors. +# Without the prior written permission of MediaTek inc. and/or its licensors, +# any reproduction, modification, use or disclosure of MediaTek Software, +# and information contained herein, in whole or in part, shall be strictly prohibited. + +# MediaTek Inc. (C) 2010. All rights reserved. +# +# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON +# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH +# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES +# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES +# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK +# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR +# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND +# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO +# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +# +# The following software/firmware and/or related documentation ("MediaTek Software") +# have been modified by MediaTek Inc. All revisions are subject to any receiver's +# applicable license agreements with MediaTek Inc. + + +# drivers/barcelona/gps/Makefile +# +# Makefile for the Barcelona GPS driver. +# +# Copyright (C) 2004,2005 TomTom BV +# Author: Dimitry Andric +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +obj-$(CONFIG_MTK_GPS) += gps.o + +# EOF diff --git a/drivers/mtk_wcn_combo/gps/gps.c b/drivers/mtk_wcn_combo/gps/gps.c new file mode 100755 index 000000000000..c487076a99f5 --- /dev/null +++ b/drivers/mtk_wcn_combo/gps/gps.c @@ -0,0 +1,1138 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + */ +/* MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +/* drivers/barcelona/gps/gps.c + * + * Implementation of the GPS driver. + * + * Copyright (C) 2004,2005 TomTom BV + * Authors: + * Jeroen Taverne + * Dimitry Andric + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/******************************************************************************* +* Dependency +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_ARCH_MT6573) +#include +#include +#elif defined(CONFIG_ARCH_MT6575) +#include +#include +#elif defined(CONFIG_ARCH_MT6516) +#include +#include +#include +#include +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +struct mt3326_gps_hardware{ + int (*ext_power_on)(int); + int (*ext_power_off)(int); +}; + +struct mt3326_gps_hardware mt3326_gps_hw = { + .ext_power_on = NULL, + .ext_power_off = NULL, +}; + +/****************************************************************************** + * Function Configuration +******************************************************************************/ +//#define FAKE_DATA +#define GPS_SUSPEND_RESUME +#define GPS_CONFIGURABLE_RESET_DELAY +/****************************************************************************** + * Definition +******************************************************************************/ +/* device name and major number */ +#define GPS_DEVNAME "mt3326-gps" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#define GPS_DBG_NONE(fmt, arg...) do {} while (0) +#define GPS_DBG_FUNC(fmt, arg...) printk(KERN_INFO PFX "%s: " fmt, __FUNCTION__ ,##arg) + +#define GPS_ERR(fmt, arg...) printk(KERN_ERR PFX "%s: " fmt, __FUNCTION__ ,##arg) +#define GPS_WARN(fmt, arg...) printk(KERN_WARNING PFX "%s: " fmt, __FUNCTION__ ,##arg) +#define GPS_NOTICE(fmt, arg...) printk(KERN_NOTICE PFX "%s: " fmt, __FUNCTION__ ,##arg) +#define GPS_INFO(fmt, arg...) printk(KERN_INFO PFX "%s: " fmt, __FUNCTION__ ,##arg) +#define GPS_TRC_FUNC(f) printk(PFX "<%s>\n", __FUNCTION__); +#define GPS_TRC_VERBOSE(fmt, arg...) printk(PFX fmt, ##arg) + +#define PFX "GPS: " +#define GPS_DBG GPS_DBG_FUNC +#define GPS_TRC GPS_DBG_NONE //GPS_TRC_FUNC +#define GPS_VER GPS_DBG_NONE //GPS_TRC_VERBOSE +#define IH_DBG GPS_DBG_NONE +/******************************************************************************* +* structure & enumeration +*******************************************************************************/ +enum { + GPS_PWRCTL_UNSUPPORTED = 0xFF, + GPS_PWRCTL_OFF = 0x00, + GPS_PWRCTL_ON = 0x01, + GPS_PWRCTL_RST = 0x02, + GPS_PWRCTL_OFF_FORCE = 0x03, + GPS_PWRCTL_RST_FORCE = 0x04, + GPS_PWRCTL_MAX = 0x05, +}; +enum { + GPS_PWR_UNSUPPORTED = 0xFF, + GPS_PWR_RESUME = 0x00, + GPS_PWR_SUSPEND = 0x01, + GPS_PWR_MAX = 0x02, +}; +enum { + GPS_STATE_UNSUPPORTED = 0xFF, + GPS_STATE_OFF = 0x00, /*cleanup/power off, default state*/ + GPS_STATE_INIT = 0x01, /*init*/ + GPS_STATE_START = 0x02, /*start navigating*/ + GPS_STATE_STOP = 0x03, /*stop navigating*/ + GPS_STATE_DEC_FREQ = 0x04, + GPS_STATE_SLEEP = 0x05, + GPS_STATE_MAX = 0x06, +}; +enum { + GPS_PWRSAVE_UNSUPPORTED = 0xFF, + GPS_PWRSAVE_DEC_FREQ = 0x00, + GPS_PWRSAVE_SLEEP = 0x01, + GPS_PWRSAVE_OFF = 0x02, + GPS_PWRSAVE_MAX = 0x03, +}; +/*---------------------------------------------------------------------------*/ +struct gps_data{ + int dat_len; + int dat_pos; + char dat_buf[4096]; + spinlock_t lock; + wait_queue_head_t read_wait; + struct semaphore sem; +}; +/*---------------------------------------------------------------------------*/ +struct gps_sta_itm { /*gps status record*/ + unsigned char year; /*current year - 1900*/ + unsigned char month; /*1~12*/ + unsigned char day; /*1~31*/ + unsigned char hour; /*0~23*/ + + unsigned char minute; /*0~59*/ + unsigned char sec; /*0~59*/ + unsigned char count; /*reborn count*/ + unsigned char reason; /*reason: 0: timeout; 1: force*/ +}; +/*---------------------------------------------------------------------------*/ +struct gps_sta_obj { + int index; + struct gps_sta_itm items[32]; +}; +/*---------------------------------------------------------------------------*/ +struct gps_drv_obj { + unsigned char pwrctl; + unsigned char suspend; + unsigned char state; + unsigned char pwrsave; + int rdelay; /*power reset delay*/ + struct kobject *kobj; + struct mutex sem; + struct gps_sta_obj status; + struct mt3326_gps_hardware *hw; +}; +/*---------------------------------------------------------------------------*/ +struct gps_dev_obj { + struct class *cls; + struct device *dev; + dev_t devno; + struct cdev chdev; + struct mt3326_gps_hardware *hw; +}; +/****************************************************************************** + * local variables +******************************************************************************/ +static struct gps_data gps_private= {0}; + +#if defined(FAKE_DATA) +static char fake_data[] = { +"$GPGGA,135036.000,2446.3713,N,12101.3605,E,1,5,1.61,191.1,M,15.1,M,,*51\r\n" +"$GPGSA,A,3,22,18,14,30,31,,,,,,,,1.88,1.61,0.98*09\r\n" +"$GPGSV,2,1,6,18,83,106,32,22,58,324,35,30,45,157,35,14,28,308,32*44\r\n" +"$GPGSV,2,2,6,40,21,254,,31,17,237,29*42\r\n" +"$GPRMC,135036.000,A,2446.37125,N,12101.36054,E,0.243,56.48,140109,,A*46\r\n" +"$GPVTG,56.48,T,,M,0.243,N,0.451,K,A*07\r\n" +}; +#endif //FAKE_DATA + +/*this should be synchronous with mnld.c +enum { + MNL_RESTART_NONE = 0x00, //recording the 1st of mnld + MNL_RESTART_TIMEOUT_INIT = 0x01, //restart due to timeout + MNL_RESTART_TIMEOUT_MONITOR = 0x02, //restart due to timeout + MNL_RESTART_TIMEOUT_WAKEUP = 0x03, //restart due to timeout + MNL_RESTART_TIMEOUT_TTFF = 0x04, //restart due to TTFF timeout + MNL_RESTART_FORCE = 0x04, //restart due to external command +}; +*/ +/*---------------------------------------------------------------------------*/ +static char *str_reason[] = {"none", "init", "monitor", "wakeup", "TTFF", "force", "unknown"}; +/****************************************************************************** + * Functions +******************************************************************************/ +static inline void mt3326_gps_power(struct mt3326_gps_hardware *hw, + unsigned int on, unsigned int force) +{ + /*FIX ME: PM_api should provide a function to get current status*/ + static unsigned int power_on = 1; + int err; + GPS_DBG("Switching GPS device %s\n", on ? "on" : "off"); + if (!hw) { + GPS_ERR("null pointer!!\n"); + return; + } + + if (power_on == on) { + GPS_DBG("ignore power control: %d\n", on); + } else if (on) { + /*power on*/ + if (hw->ext_power_on) { + err = hw->ext_power_on(0); + if (err) + GPS_ERR("ext_power_on fail\n"); + } +#if 0 +#ifndef MTK_MT6620 + if (!hwPowerOn(MT6516_POWER_V3GTX, VOL_2800,"MT3326")) { + GPS_ERR("power on fails!!\n"); + return; + } +#endif +#endif + if (hw->ext_power_on) { + err = hw->ext_power_on(1); + if (err) + GPS_ERR("ext_power_on fail\n"); + } + + #if 0 + if (!hwEnableClock(MT6516_PDN_PERI_UART2,"MT3326")) + GPS_ERR("enable clock fail"); + #endif + mdelay(120); + } else { + #if 0 + if (!hwDisableClock(MT6516_PDN_PERI_UART2,"MT3326")) + GPS_ERR("disable clock fail\n"); + #endif + if (hw->ext_power_off) { + err = hw->ext_power_off(force); + if (err) + GPS_ERR("ext_power_off fail\n"); + } +#if 0 +#ifndef MTK_MT6620 + if (force) { + /*TO FIX: the LDO pin is shared between modem + and external devices, it doesn't work if only + calling hwPowerDown*/ + typedef enum + { + V3GTX_ENABLE_WITH_SRCLKEN = 0, + V3GTX_ENABLE_WITH_V3GTX_EN + }v3gtx_on_sel_enum; + extern void pmic_v3gtx_on_sel(v3gtx_on_sel_enum); + pmic_v3gtx_on_sel(V3GTX_ENABLE_WITH_V3GTX_EN); + GPS_DBG("force power off!!\n"); + } + + if (!hwPowerDown(MT6516_POWER_V3GTX,"MT3326" )) + GPS_ERR("power off fail\n"); +#endif +#endif + } + power_on = on; +} +/*****************************************************************************/ +static inline void mt3326_gps_reset(struct mt3326_gps_hardware *hw, int delay, int force) +{ + mt3326_gps_power(hw, 1, FALSE); + mdelay(delay); + mt3326_gps_power(hw, 0, force); + mdelay(delay); + mt3326_gps_power(hw, 1, FALSE); +} +/******************************************************************************/ +static inline int mt3326_gps_set_suspend(struct gps_drv_obj* obj, + unsigned char suspend) +{ + if (!obj) + return -1; + mutex_lock(&obj->sem); + if (obj->suspend != suspend) { + GPS_DBG("issue sysfs_notify : %p\n", obj->kobj->sd); + sysfs_notify(obj->kobj, NULL, "suspend"); + } + obj->suspend = suspend; + mutex_unlock(&obj->sem); + return 0; +} +/******************************************************************************/ +static inline int mt3326_gps_set_pwrctl(struct gps_drv_obj* obj, + unsigned char pwrctl) +{ + int err = 0; + if (!obj) + return -1; + mutex_lock(&obj->sem); + + if ((pwrctl == GPS_PWRCTL_ON) || (pwrctl == GPS_PWRCTL_OFF)) { + obj->pwrctl = pwrctl; + mt3326_gps_power(obj->hw, pwrctl, FALSE); + } else if (pwrctl == GPS_PWRCTL_OFF_FORCE) { + obj->pwrctl = pwrctl; + mt3326_gps_power(obj->hw, pwrctl, TRUE); + } else if (pwrctl == GPS_PWRCTL_RST) { + mt3326_gps_reset(obj->hw, obj->rdelay, FALSE); + obj->pwrctl = GPS_PWRCTL_ON; + } else if (pwrctl == GPS_PWRCTL_RST_FORCE) { + mt3326_gps_reset(obj->hw, obj->rdelay, TRUE); + obj->pwrctl = GPS_PWRCTL_ON; + } else { + err = -1; + } + mutex_unlock(&obj->sem); + return err; +} + /******************************************************************************/ +static inline int mt3326_gps_set_status(struct gps_drv_obj* obj, + const char* buf, size_t count) +{ + int err = 0; + int year, mon, day, hour, minute, sec, cnt, reason, idx; + if (!obj) + return -1; + + mutex_lock(&obj->sem); + if (sscanf(buf, "(%d/%d/%d %d:%d:%d) - %d/%d", &year, &mon, &day, + &hour, &minute, &sec, &cnt, &reason) == 8) { + int number = (int)(sizeof(obj->status.items)/sizeof(obj->status.items[0])); + idx = obj->status.index % number; + obj->status.items[idx].year = (unsigned char)year; + obj->status.items[idx].month = (unsigned char)mon; + obj->status.items[idx].day = (unsigned char)day; + obj->status.items[idx].hour = (unsigned char)hour; + obj->status.items[idx].minute= (unsigned char)minute; + obj->status.items[idx].sec = (unsigned char)sec; + obj->status.items[idx].count = (unsigned char)cnt; + obj->status.items[idx].reason= (unsigned char)reason; + obj->status.index ++; + } else { + err = -1; + } + mutex_unlock(&obj->sem); + return err; +} +/******************************************************************************/ +static inline int mt3326_gps_set_state(struct gps_drv_obj* obj, + unsigned char state) +{ + int err = 0; + if (!obj) + return -1; + mutex_lock(&obj->sem); + if (state < GPS_STATE_MAX) + obj->state = state; + else + err = -1; + mutex_unlock(&obj->sem); + return err; +} +/******************************************************************************/ +static inline int mt3326_gps_set_pwrsave(struct gps_drv_obj* obj, + unsigned char pwrsave) +{ + int err = 0; + + if (!obj) + return -1; + mutex_lock(&obj->sem); + if (pwrsave < GPS_PWRSAVE_MAX) + obj->pwrsave = pwrsave; + else + err = -1; + mutex_unlock(&obj->sem); + return err; +} +/******************************************************************************/ +static inline int mt3326_gps_dev_suspend(struct gps_drv_obj *obj) +{ +#if defined(GPS_SUSPEND_RESUME) + int err; + + if ((err = mt3326_gps_set_suspend(obj, GPS_PWR_SUSPEND))) + GPS_DBG("set suspend fail: %d\n", err); + if ((err = mt3326_gps_set_pwrctl(obj, GPS_PWRCTL_OFF))) + GPS_DBG("set pwrctl fail: %d\n", err); + return err; +#endif +} +/******************************************************************************/ +static inline int mt3326_gps_dev_resume(struct gps_drv_obj *obj) +{ +#if defined(GPS_SUSPEND_RESUME) + int err; + + if ((err = mt3326_gps_set_suspend(obj, GPS_PWR_RESUME))) + GPS_DBG("set suspend fail: %d\n", err); + /*don't power on device automatically*/ + return err; +#endif +} +/******************************************************************************/ +static ssize_t mt3326_show_pwrctl(struct device* dev, + struct device_attribute *attr, char *buf) +{ + struct gps_drv_obj *obj; + ssize_t res; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + res = snprintf(buf, PAGE_SIZE, "%d\n", obj->pwrctl); + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_pwrctl(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + if ((count == 1) || + ((count == 2) && (buf[1] == '\n'))) { + unsigned char pwrctl = buf[0] - '0'; + if (!mt3326_gps_set_pwrctl(obj, pwrctl)) + return count; + } + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +static ssize_t mt3326_show_suspend(struct device* dev, + struct device_attribute *attr, char *buf) +{ + struct gps_drv_obj *obj; + ssize_t res; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + res = snprintf(buf, PAGE_SIZE, "%d\n", obj->suspend); + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_suspend(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + if ((count == 1) || + ((count == 2) && (buf[1] == '\n'))) { + unsigned char suspend = buf[0] - '0'; + if (suspend == GPS_PWR_SUSPEND) { + if (!mt3326_gps_dev_suspend(obj)) + return count; + } else if (suspend == GPS_PWR_RESUME) { + if (!mt3326_gps_dev_resume(obj)) + return count; + } + } + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +static ssize_t mt3326_show_status(struct device* dev, + struct device_attribute *attr, char *buf) +{ + int res, idx, num, left, cnt, len; + struct gps_drv_obj *obj; + char *reason = NULL; + int reason_max = (int)(sizeof(str_reason)/sizeof(str_reason[0])); + + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + num = (int)(sizeof(obj->status.items)/sizeof(obj->status.items[0])); + left = PAGE_SIZE; + cnt = 0; + len = 0; + for (idx = 0; idx < num; idx++) { + if (obj->status.items[idx].month == 0) + continue; + if (obj->status.items[idx].reason >= reason_max) + reason = str_reason[reason_max-1]; + else + reason = str_reason[obj->status.items[idx].reason]; + cnt = snprintf(buf+len, left, "[%d] %.4d/%.2d/%.2d %.2d:%.2d:%.2d - %d, %s\n", idx, + obj->status.items[idx].year + 1900, obj->status.items[idx].month, + obj->status.items[idx].day, obj->status.items[idx].hour, + obj->status.items[idx].minute, obj->status.items[idx].sec, + obj->status.items[idx].count, reason); + left -= cnt; + len += cnt; + } + res = PAGE_SIZE - left; + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_status(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + if (!mt3326_gps_set_status(obj, buf, count)) + return count; + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +static ssize_t mt3326_show_state(struct device* dev, + struct device_attribute *attr, char *buf) +{ + ssize_t res; + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + res = snprintf(buf, PAGE_SIZE, "%d\n", obj->state); + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_state(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + if ((count == 1) || + ((count == 2) && (buf[1] == '\n'))) { /*To Do: dynamic change according to input*/ + unsigned char state = buf[0] - '0'; + if (!mt3326_gps_set_state(obj, state)) + return count; + } + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +static ssize_t mt3326_show_pwrsave(struct device* dev, + struct device_attribute *attr, char *buf) +{ + ssize_t res; + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + res = snprintf(buf, PAGE_SIZE, "%d\n", obj->pwrsave); + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_pwrsave(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + if ((count == 1) || + ((count == 2) && (buf[1] == '\n'))) { + unsigned char pwrsave = buf[0] - '0'; + if (!mt3326_gps_set_pwrsave(obj, pwrsave)) + return count; + } + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +#if defined(GPS_CONFIGURABLE_RESET_DELAY) +/******************************************************************************/ +static ssize_t mt3326_show_rdelay(struct device* dev, + struct device_attribute *attr, char *buf) +{ + ssize_t res; + struct gps_drv_obj *obj; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + mutex_lock(&obj->sem); + res = snprintf(buf, PAGE_SIZE, "%d\n", obj->rdelay); + mutex_unlock(&obj->sem); + return res; +} +/******************************************************************************/ +static ssize_t mt3326_store_rdelay(struct device* dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gps_drv_obj *obj; + int rdelay; + char *end; + if (!dev) { + GPS_DBG("dev is null!!\n"); + return 0; + } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) { + GPS_DBG("drv data is null!!\n"); + return 0; + } + end = (char*)buf+count; + rdelay = (int)simple_strtol(buf, &end, 10); + if (rdelay < 2000) { + mutex_lock(&obj->sem); + obj->rdelay = rdelay; + mutex_unlock(&obj->sem); + return count; + } + GPS_DBG("invalid content: '%s', length = %d\n", buf, count); + return count; +} +/******************************************************************************/ +#endif +/******************************************************************************/ +DEVICE_ATTR(pwrctl, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_pwrctl, mt3326_store_pwrctl); +DEVICE_ATTR(suspend, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_suspend,mt3326_store_suspend); +DEVICE_ATTR(status, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_status, mt3326_store_status); +DEVICE_ATTR(state, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_state, mt3326_store_state); +DEVICE_ATTR(pwrsave, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_pwrsave,mt3326_store_pwrsave); +#if defined(GPS_CONFIGURABLE_RESET_DELAY) +DEVICE_ATTR(rdelay, S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_rdelay ,mt3326_store_rdelay); +#endif +static struct device_attribute *gps_attr_list[] = { + &dev_attr_pwrctl, + &dev_attr_suspend, + &dev_attr_status, + &dev_attr_state, + &dev_attr_pwrsave, +#if defined(GPS_CONFIGURABLE_RESET_DELAY) + &dev_attr_rdelay, +#endif +}; +/******************************************************************************/ +static int mt3326_gps_create_attr(struct device *dev) +{ + int idx, err = 0; + int num = (int)(sizeof(gps_attr_list)/sizeof(gps_attr_list[0])); + if (!dev) + return -EINVAL; + + GPS_TRC(); + for (idx = 0; idx < num; idx++) { + if ((err = device_create_file(dev, gps_attr_list[idx]))) { + GPS_DBG("device_create_file (%s) = %d\n", gps_attr_list[idx]->attr.name, err); + break; + } + } + + return err; +} +/******************************************************************************/ +static int mt3326_gps_delete_attr(struct device *dev) +{ + int idx ,err = 0; + int num = (int)(sizeof(gps_attr_list)/sizeof(gps_attr_list[0])); + + if (!dev) + return -EINVAL; + + for (idx = 0; idx < num; idx++) + device_remove_file(dev, gps_attr_list[idx]); + + return err; +} +/******************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) +static int mt3326_gps_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} +#else +long mt3326_gps_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + GPS_DBG("mt3326_gps_unlocked_ioctl!!\n"); + return -ENOIOCTLCMD; +} +#endif +/*****************************************************************************/ +static int mt3326_gps_open(struct inode *inode, struct file *file) +{ + GPS_TRC(); + file->private_data = &gps_private; //all files share the same buffer + return nonseekable_open(inode, file); +} +/*****************************************************************************/ +static int mt3326_gps_release(struct inode *inode, struct file *file) +{ + struct gps_data *dev = file->private_data; + + GPS_TRC(); + + if (dev) + file->private_data = NULL; + + return 0; +} +/******************************************************************************/ +static ssize_t mt3326_gps_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct gps_data *dev = file->private_data; + ssize_t ret = 0; + int copy_len = 0; + + GPS_TRC(); + + if (!dev) + return -EINVAL; + + //printk("%s: %d\n", __FUNCTION__, dev->dat_len); + if (signal_pending(current)) + return -ERESTARTSYS; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + if (dev->dat_len == 0){ /*no data to be read*/ + up(&dev->sem); + if (file->f_flags & O_NONBLOCK) /*non-block mode*/ + return -EAGAIN; + do {/*block mode*/ + ret = wait_event_interruptible(dev->read_wait, (dev->dat_len > 0)); + if (ret == -ERESTARTSYS) + return -ERESTARTSYS; + }while(ret == 0); + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + } + + /*data is available*/ + copy_len = (dev->dat_len < (int)count) ? (dev->dat_len) : (int)(count); + if (copy_to_user(buf, dev->dat_buf+dev->dat_pos, (unsigned long)copy_len)){ + GPS_DBG("copy_to_user error: 0x%X 0x%X, %d\n", (unsigned int)buf, (unsigned int)dev->dat_buf, dev->dat_len); + ret = -EFAULT; + } else { + GPS_VER("mt3326_gps_read(%d,%d,%d) = %d\n", count, dev->dat_pos, dev->dat_len, copy_len); + if (dev->dat_len > (copy_len+dev->dat_pos)) { + dev->dat_pos += copy_len; + } else { + dev->dat_len = 0; + dev->dat_pos = 0; + } + ret = copy_len; + } + + up(&dev->sem); + GPS_VER("%s return %d bytes\n", __FUNCTION__, ret); + return ret; +} +/******************************************************************************/ +static ssize_t mt3326_gps_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + struct gps_data *dev = file->private_data; + ssize_t ret = 0; + + GPS_TRC(); + + if (!dev) + return -EINVAL; + + if (!count) /*no data written*/ + return 0; + + if (signal_pending(current)) + return -ERESTARTSYS; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + if (copy_from_user(dev->dat_buf, buf, count)) { + GPS_DBG("copy_from_user error"); + ret = -EFAULT; + } else { + dev->dat_len = count; + dev->dat_pos = 0; + ret = count; + } + up(&dev->sem); + wake_up_interruptible(&dev->read_wait); + GPS_VER("%s: write %d bytes\n", __FUNCTION__, dev->dat_len); + return ret; +} +/******************************************************************************/ +static unsigned int mt3326_gps_poll(struct file *file, poll_table *wait) +{ + struct gps_data *dev = file->private_data; + unsigned int mask = 0; + + GPS_TRC(); + + if (!dev) + return 0; + + down(&dev->sem); + poll_wait(file, &dev->read_wait, wait); + if (dev->dat_len != 0) /*readable if data is available*/ + mask = (POLLIN|POLLRDNORM) | (POLLOUT|POLLWRNORM); + else /*always writable*/ + mask = (POLLOUT|POLLWRNORM); + up(&dev->sem); + GPS_VER("%s: mask : 0x%X\n", __FUNCTION__, mask); + return mask; +} +/*****************************************************************************/ +/* Kernel interface */ +static struct file_operations mt3326_gps_fops = { + .owner = THIS_MODULE, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + .ioctl = mt3326_gps_ioctl, +#else + .unlocked_ioctl = mt3326_gps_unlocked_ioctl, +#endif + .open = mt3326_gps_open, + .read = mt3326_gps_read, + .write = mt3326_gps_write, + .release = mt3326_gps_release, + .poll = mt3326_gps_poll, +}; +/*****************************************************************************/ +extern unsigned int reset_state; +/*****************************************************************************/ +static void mt3326_gps_hw_init(struct mt3326_gps_hardware *hw) +{ + mt3326_gps_power(hw, 1, FALSE); +} +/*****************************************************************************/ +static void mt3326_gps_hw_exit(struct mt3326_gps_hardware *hw) +{ + mt3326_gps_power(hw, 0, FALSE); +} +/*****************************************************************************/ +static int mt3326_gps_probe(struct platform_device *dev) +{ + int ret = 0, err = 0; + struct gps_drv_obj *drvobj = NULL; + struct mt3326_gps_hardware *hw = (struct mt3326_gps_hardware*)dev->dev.platform_data; + struct gps_dev_obj *devobj = NULL; + + if (!(devobj = kzalloc(sizeof(*devobj), GFP_KERNEL))) + { + GPS_ERR("-ENOMEM\n"); + err = -ENOMEM; + goto error; + } + + mt3326_gps_hw_init(hw); + + GPS_DBG("Registering chardev\n"); + ret = alloc_chrdev_region(&devobj->devno, 0, 1, GPS_DEVNAME); + if (ret) { + GPS_ERR("alloc_chrdev_region fail: %d\n", ret); + goto error; + } else { + GPS_DBG("major: %d, minor: %d\n", MAJOR(devobj->devno), MINOR(devobj->devno)); + } + cdev_init(&devobj->chdev, &mt3326_gps_fops); + devobj->chdev.owner = THIS_MODULE; + err = cdev_add(&devobj->chdev, devobj->devno, 1); + if (err) { + GPS_ERR("cdev_add fail: %d\n", err); + goto error; + } + + if (!(drvobj = kmalloc(sizeof(*drvobj), GFP_KERNEL))) { + err = -ENOMEM; + goto error; + } + memset(drvobj, 0 ,sizeof(*drvobj)); + + devobj->cls = class_create(THIS_MODULE, "gpsdrv"); + if (IS_ERR(devobj->cls)) { + GPS_ERR("Unable to create class, err = %d\n", (int)PTR_ERR(devobj->cls)); + goto error; + } + devobj->dev = device_create(devobj->cls, NULL, devobj->devno, drvobj, "gps"); + drvobj->hw = hw; + drvobj->pwrctl = 0; + drvobj->suspend = 0; + drvobj->state = GPS_STATE_UNSUPPORTED; + drvobj->pwrsave = GPS_PWRSAVE_UNSUPPORTED; + drvobj->rdelay = 50; + drvobj->kobj = &devobj->dev->kobj; + mutex_init(&drvobj->sem); + + if ((err = mt3326_gps_create_attr(devobj->dev))) + goto error; + + /*initialize members*/ + spin_lock_init(&gps_private.lock); + init_waitqueue_head(&gps_private.read_wait); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + init_MUTEX(&gps_private.sem); +#else + sema_init(&gps_private.sem, 1); +#endif + gps_private.dat_len = 0; + gps_private.dat_pos = 0; + memset(gps_private.dat_buf, 0x00, sizeof(gps_private.dat_buf)); + + /*set platform data: + a new device created for gps */ + platform_set_drvdata(dev, devobj); + + GPS_DBG("Done\n"); + return 0; + +error: + if (err == 0) + cdev_del(&devobj->chdev); + if (ret == 0) + unregister_chrdev_region(devobj->devno, 1); + return -1; +} +/*****************************************************************************/ +static int mt3326_gps_remove(struct platform_device *dev) +{ + struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev); + struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev); + int err; + + if (!devobj || !drvobj) { + GPS_ERR("null pointer: %p, %p\n", devobj, drvobj); + return -1; + } + + GPS_DBG("Unregistering chardev\n"); + kfree(devobj); + + cdev_del(&devobj->chdev); + unregister_chrdev_region(devobj->devno, 1); + + mt3326_gps_hw_exit(devobj->hw); + if ((err = mt3326_gps_delete_attr(devobj->dev))) + GPS_ERR("delete attr fails: %d\n", err); + device_destroy(devobj->cls, devobj->devno); + class_destroy(devobj->cls); + GPS_DBG("Done\n"); + return 0; +} +/*****************************************************************************/ +static void mt3326_gps_shutdown(struct platform_device *dev) +{ + struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev); + GPS_DBG("Shutting down\n"); + mt3326_gps_hw_exit(devobj->hw); +} +/*****************************************************************************/ +#ifdef CONFIG_PM +/*****************************************************************************/ +static int mt3326_gps_suspend(struct platform_device *dev, pm_message_t state) +{ + int err = 0; + struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev); + struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev); + + if (!devobj || !drvobj) { + GPS_ERR("null pointer: %p, %p\n", devobj, drvobj); + return -1; + } + + GPS_DBG("dev = %p, event = %u,", dev, state.event); + if (state.event == PM_EVENT_SUSPEND) { + err = mt3326_gps_dev_suspend(drvobj); + } + return err; +} +/*****************************************************************************/ +static int mt3326_gps_resume(struct platform_device *dev) +{ + struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev); + struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev); + + GPS_DBG(""); + return mt3326_gps_dev_resume(drvobj); +} +/*****************************************************************************/ +#endif /* CONFIG_PM */ +/*****************************************************************************/ +static struct platform_driver mt3326_gps_driver = +{ + .probe = mt3326_gps_probe, + .remove = mt3326_gps_remove, + .shutdown = mt3326_gps_shutdown, +#if defined(CONFIG_PM) + .suspend = mt3326_gps_suspend, + .resume = mt3326_gps_resume, +#endif + .driver = { + .name = GPS_DEVNAME, + .bus = &platform_bus_type, + }, +}; + +struct platform_device mt3326_device_gps = { + .name = "mt3326-gps", + .id = -1, + .dev = { + .platform_data = &mt3326_gps_hw, + }, +}; + +/*****************************************************************************/ +static int __init mt3326_gps_mod_init(void) +{ + int ret = 0; + GPS_TRC(); + + //ret = driver_register(&mt3326_gps_driver); + ret = platform_driver_register(&mt3326_gps_driver); + if (ret != 0){ + GPS_ERR("platform_driver_register error\n"); + } + ret = platform_device_register(&mt3326_device_gps); + + if (ret != 0){ + GPS_ERR("platform_device_register error\n"); + } + return ret; +} +/*****************************************************************************/ +static void __exit mt3326_gps_mod_exit(void) +{ + GPS_TRC(); + platform_driver_unregister(&mt3326_gps_driver); +} +/*****************************************************************************/ +module_init(mt3326_gps_mod_init); +module_exit(mt3326_gps_mod_exit); +/*****************************************************************************/ +MODULE_AUTHOR("MingHsien Hsieh "); +MODULE_DESCRIPTION("MT3326 GPS Driver"); +MODULE_LICENSE("GPL"); + + + diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig old mode 100644 new mode 100755 index 9898263ac94f..eee1ef2409ed --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -31,7 +31,7 @@ config CFG80211 config NL80211_TESTMODE bool "nl80211 testmode command" - depends on CFG80211 && (MT5931 || MT5931_MT6622) + depends on CFG80211 && (MT5931 || MT5931_MT6622 || MTK_COMBO) help The nl80211 testmode command helps implementing things like factory calibration or validation tools for wireless chips.