| /* |
| ** $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 "precomp.h" |
| |
| #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)) |
| #define CMD_MIRACAST "MIRACAST" |
| /* miracast related definition */ |
| #define MIRACAST_MODE_OFF 0 |
| #define MIRACAST_MODE_SOURCE 1 |
| #define MIRACAST_MODE_SINK 2 |
| #define CMD_SET_CHIP "SET_CHIP" |
| static UINT_8 g_ucMiracastMode = MIRACAST_MODE_OFF; |
| typedef struct priv_driver_cmd_s { |
| char *buf; |
| int used_len; |
| int total_len; |
| } priv_driver_cmd_t; |
| |
| /******************************************************************************* |
| * 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] = %lx, size of PTA_IPC_T = %d.\n", |
| (UINT_32)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", (UINT32)pu4IntBuf[1])); |
| } |
| break; |
| |
| #if CFG_ENABLE_WIFI_DIRECT |
| case PRIV_CMD_P2P_MODE: |
| { |
| /* no use, move to set_p2p_mode_handler() */ |
| extern int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode); |
| PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode; |
| p2pmode.u4Enable = pu4IntBuf[1]; |
| p2pmode.u4Mode = pu4IntBuf[2]; |
| set_p2p_mode_handler(prNetDev, p2pmode); |
| #if 0 |
| extern BOOLEAN fgIsResetting; |
| extern BOOLEAN g_u4HaltFlag; |
| extern spinlock_t g_p2p_lock; |
| extern int g_u4P2PEnding; |
| extern int g_u4P2POnOffing; |
| PARAM_CUSTOM_P2P_SET_STRUC_T rSetP2P; |
| WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; |
| BOOLEAN fgIsP2PEnding; |
| GLUE_SPIN_LOCK_DECLARATION(); |
| |
| /* avoid remove & p2p off command simultaneously */ |
| GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); |
| fgIsP2PEnding = g_u4P2PEnding; |
| g_u4P2POnOffing = 1; |
| GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); |
| |
| if (fgIsP2PEnding == 1) |
| { |
| /* skip the command if we are removing */ |
| GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); |
| g_u4P2POnOffing = 0; |
| GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); |
| break; |
| } |
| rSetP2P.u4Enable = pu4IntBuf[1]; |
| rSetP2P.u4Mode = pu4IntBuf[2]; |
| |
| if(!rSetP2P.u4Enable) { |
| p2pNetUnregister(prGlueInfo, TRUE); |
| } |
| |
| |
| /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ |
| /* |
| Scenario: |
| 1. System enters suspend/resume but not yet enter wlanearlysuspend() |
| or wlanlateresume(); |
| |
| 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() |
| and get g_halt_sem then do glRegisterEarlySuspend() or |
| glUnregisterEarlySuspend(); |
| |
| But system suspend/resume procedure is not yet finished so we |
| suspend; |
| |
| 3. System switches back to do suspend/resume procedure and execute |
| kalIoctl(). But driver does not yet release g_halt_sem so system |
| suspend in wlanearlysuspend() or wlanlateresume(); |
| |
| ==> deadlock occurs. |
| */ |
| if ((!rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && |
| (fgIsResetting == FALSE)) |
| { |
| /* fgIsP2PRegistered == TRUE means P2P is enabled */ |
| DBGLOG(P2P, INFO, ("p2pEalySuspendReg\n")); |
| p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p remove */ |
| } |
| |
| DBGLOG(P2P, INFO, ("wlanoidSetP2pMode 0x%p %d %d\n", &rSetP2P, rSetP2P.u4Enable, rSetP2P.u4Mode)); |
| 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); |
| DBGLOG(P2P, INFO, ("wlanoidSetP2pMode ok\n")); |
| |
| /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ |
| if ((rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && |
| (fgIsResetting == FALSE)) |
| { |
| /* fgIsP2PRegistered == TRUE means P2P on successfully */ |
| p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p on */ |
| } |
| |
| if(rSetP2P.u4Enable) { |
| p2pNetRegister(prGlueInfo, TRUE); |
| } |
| |
| GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); |
| g_u4P2POnOffing = 0; |
| GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); |
| #endif |
| } |
| 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. |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 gucBufDbgCode[1000]; |
| |
| 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; |
| } |
| |
| case PRIV_CMD_GET_BUILD_DATE_CODE: |
| { |
| UINT_8 aucBuffer[16]; |
| |
| if(kalIoctl(prGlueInfo, |
| wlanoidQueryBuildDateCode, |
| (PVOID)aucBuffer, |
| sizeof(UINT_8) * 16, |
| TRUE, |
| TRUE, |
| TRUE, |
| FALSE, |
| &u4BufLen) == WLAN_STATUS_SUCCESS) { |
| prIwReqData->data.length = sizeof(UINT_8) * 16; |
| |
| if (copy_to_user(prIwReqData->data.pointer, aucBuffer, prIwReqData->data.length)) { |
| return -EFAULT; |
| } |
| else |
| return status; |
| } |
| else { |
| return -EFAULT; |
| } |
| } |
| |
| case PRIV_CMD_GET_DEBUG_CODE: |
| { |
| wlanQueryDebugCode(prGlueInfo->prAdapter); |
| |
| kalMemSet(gucBufDbgCode, '.', sizeof(gucBufDbgCode)); |
| if (copy_to_user(prIwReqData->data.pointer, gucBufDbgCode, prIwReqData->data.length)) { |
| 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 */ |
| |
| /* ++ TDLS */ |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Parse command value in a string. |
| * |
| * @param InStr Pointer to the string buffer. |
| * @param OutStr Pointer to the next command value. |
| * @param OutLen Record the resident buffer length. |
| * |
| * @retval Command value. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 |
| CmdStringDecParse( |
| IN UINT_8 *InStr, |
| OUT UINT_8 **OutStr, |
| OUT UINT_32 *OutLen |
| ) |
| { |
| unsigned char Charc, *Buf; |
| unsigned int Num; |
| int Maxloop; |
| int ReadId; |
| int TotalLen; |
| |
| |
| /* init */ |
| Num = 0; |
| Maxloop = 0; |
| ReadId = 0; |
| Buf = (unsigned char *)InStr; |
| TotalLen = *OutLen; |
| *OutStr = Buf; |
| |
| /* sanity check */ |
| if (Buf[0] == 0x00) |
| return 0; |
| |
| /* check the value is decimal or hex */ |
| if ((Buf[ReadId] == 'x') || |
| ((Buf[ReadId] == '0') && (Buf[ReadId+1] == 'x'))) |
| { |
| /* skip x or 0x */ |
| if (Buf[ReadId] == 'x') |
| ReadId ++; |
| else |
| ReadId += 2; |
| |
| /* translate the hex number */ |
| while(Maxloop++ < 10) |
| { |
| Charc = Buf[ReadId]; |
| if ((Charc >= 0x30) && (Charc <= 0x39)) |
| Charc -= 0x30; |
| else if ((Charc >= 'a') && (Charc <= 'f')) |
| Charc -= 'a'; |
| else if ((Charc >= 'A') && (Charc <= 'F')) |
| Charc -= 'A'; |
| else |
| break; /* exit the parsing */ |
| Num = Num * 16 + Charc + 10; |
| ReadId ++; |
| TotalLen --; |
| } |
| } |
| else |
| { |
| /* translate the decimal number */ |
| while(Maxloop++ < 10) |
| { |
| Charc = Buf[ReadId]; |
| if ((Charc < 0x30) || (Charc > 0x39)) |
| break; /* exit the parsing */ |
| Charc -= 0x30; |
| Num = Num * 10 + Charc; |
| ReadId ++; |
| TotalLen --; |
| } |
| } |
| |
| if (Buf[ReadId] == 0x00) |
| *OutStr = &Buf[ReadId]; |
| else |
| *OutStr = &Buf[ReadId+1]; /* skip the character: _ */ |
| |
| *OutLen = TotalLen-1; /* skip the character: _ */ |
| return Num; |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Parse command MAC address in a string. |
| * |
| * @param InStr Pointer to the string buffer. |
| * @param OutStr Pointer to the next command value. |
| * @param OutLen Record the resident buffer length. |
| * |
| * @retval Command value. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 |
| CmdStringMacParse( |
| IN UINT_8 *InStr, |
| OUT UINT_8 **OutStr, |
| OUT UINT_32 *OutLen, |
| OUT UINT_8 *OutMac |
| ) |
| { |
| unsigned char Charc, *Buf; |
| unsigned int Num; |
| int Maxloop; |
| int ReadId; |
| int TotalLen; |
| |
| |
| /* init */ |
| Num = 0; |
| Maxloop = 0; |
| ReadId = 0; |
| Buf = (unsigned char *)InStr; |
| TotalLen = *OutLen; |
| *OutStr = Buf; |
| |
| /* sanity check */ |
| if (Buf[0] == 0x00) |
| return 0; |
| |
| /* parse MAC */ |
| while(Maxloop < 6) |
| { |
| Charc = Buf[ReadId]; |
| if ((Charc >= 0x30) && (Charc <= 0x39)) |
| Charc -= 0x30; |
| else if ((Charc >= 'a') && (Charc <= 'f')) |
| Charc = Charc - 'a' + 10; |
| else if ((Charc >= 'A') && (Charc <= 'F')) |
| Charc = Charc - 'A' + 10; |
| else |
| return -1; /* error, exit the parsing */ |
| |
| Num = Charc; |
| ReadId ++; |
| TotalLen --; |
| |
| Charc = Buf[ReadId]; |
| if ((Charc >= 0x30) && (Charc <= 0x39)) |
| Charc -= 0x30; |
| else if ((Charc >= 'a') && (Charc <= 'f')) |
| Charc = Charc - 'a' + 10; |
| else if ((Charc >= 'A') && (Charc <= 'F')) |
| Charc = Charc - 'A' + 10; |
| else |
| return -1; /* error, exit the parsing */ |
| |
| Num = Num * 16 + Charc; |
| ReadId += 2; /* skip the character and ':' */ |
| TotalLen -= 2; |
| |
| OutMac[Maxloop] = Num; |
| Maxloop ++; |
| } |
| |
| *OutStr = &Buf[ReadId]; /* skip the character: _ */ |
| *OutLen = TotalLen; /* skip the character: _ */ |
| return Num; |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \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. |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| int |
| priv_set_string( |
| IN struct net_device *prNetDev, |
| IN struct iw_request_info *prIwReqInfo, |
| IN union iwreq_data *prIwReqData, |
| IN char *pcExtra |
| ) |
| { |
| P_GLUE_INFO_T GlueInfo; |
| INT_32 Status; |
| UINT_32 Subcmd; |
| UINT_8 *InBuf; |
| UINT_32 InBufLen; |
| |
| |
| /* sanity check */ |
| ASSERT(prNetDev); |
| ASSERT(prIwReqInfo); |
| ASSERT(prIwReqData); |
| ASSERT(pcExtra); |
| |
| /* init */ |
| DBGLOG(REQ, INFO, ("priv_set_string (%s)(%d)\n", |
| (UINT8 *)prIwReqData->data.pointer, (INT32)prIwReqData->data.length)); |
| |
| if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) { |
| return -EINVAL; |
| } |
| GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); |
| |
| InBuf = aucOidBuf; |
| InBufLen = prIwReqData->data.length; |
| Status = 0; |
| |
| if (copy_from_user(InBuf, |
| prIwReqData->data.pointer, |
| prIwReqData->data.length)) { |
| return -EFAULT; |
| } |
| |
| Subcmd = CmdStringDecParse(prIwReqData->data.pointer, &InBuf, &InBufLen); |
| DBGLOG(REQ, INFO, ("priv_set_string> command = %u\n", (UINT32)Subcmd)); |
| |
| /* handle the command */ |
| switch(Subcmd) |
| { |
| #if (CFG_SUPPORT_TDLS == 1) |
| case PRIV_CMD_OTHER_TDLS: |
| TdlsexCmd(GlueInfo, InBuf, InBufLen); |
| break; |
| #endif /* CFG_SUPPORT_TDLS */ |
| |
| default: |
| break; |
| } |
| |
| return Status; |
| } |
| /* -- TDLS */ |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \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; |
| } |
| |
| int |
| priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) |
| { |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| P_GLUE_INFO_T prGlueInfo = NULL; |
| P_ADAPTER_T prAdapter = NULL; |
| UINT_32 u4BufLen = 0; |
| INT_32 i4BytesWritten = 0; |
| UINT_32 u4CmdLen = 0; |
| UINT_32 u4PrefixLen = 0; |
| /* INT_32 i4Argc = 0; */ |
| /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ |
| |
| PARAM_CUSTOM_CHIP_CONFIG_STRUC_T rChipConfigInfo; |
| |
| ASSERT(prNetDev); |
| if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) { |
| return -1; |
| } |
| prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); |
| prAdapter = prGlueInfo->prAdapter; |
| DBGLOG(REQ, INFO, ("priv_driver_set_chip_config command is %s\n", pcCommand)); |
| /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ |
| /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ |
| u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); |
| u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; |
| |
| kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); |
| |
| /* if(i4Argc >= 2) { */ |
| if (u4CmdLen > u4PrefixLen) { |
| |
| rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; |
| /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ |
| rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; |
| /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ |
| if( u4PrefixLen <= CHIP_CONFIG_RESP_SIZE) { |
| kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, CHIP_CONFIG_RESP_SIZE-u4PrefixLen); |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetChipConfig, |
| &rChipConfigInfo, |
| sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, TRUE,&u4BufLen); |
| } else { |
| DBGLOG(REQ, INFO, ("%s: kalIoctl Command Len > %d\n", __func__, CHIP_CONFIG_RESP_SIZE)); |
| rStatus = WLAN_STATUS_FAILURE; |
| } |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(REQ, INFO, ("%s: kalIoctl ret=%lu\n", __func__, rStatus)); |
| i4BytesWritten = -1; |
| } |
| } |
| |
| return i4BytesWritten; |
| |
| } |
| |
| int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) |
| { |
| |
| P_ADAPTER_T prAdapter = NULL; |
| P_GLUE_INFO_T prGlueInfo = NULL; |
| UINT_32 i4BytesWritten = 0; |
| /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ |
| /* UINT_32 u4BufLen = 0; */ |
| INT_32 i4Argc = 0; |
| UINT_8 ucMode = 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; |
| PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; |
| |
| ASSERT(prNetDev); |
| if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) { |
| return -1; |
| } |
| |
| prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); |
| |
| DBGLOG(REQ, LOUD, ("command is %s\n", pcCommand)); |
| wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); |
| DBGLOG(REQ, LOUD, ("argc is %ld\n", i4Argc)); |
| |
| prAdapter = prGlueInfo->prAdapter; |
| if (i4Argc >= 2) { |
| |
| ucMode = kalStrtoul(apcArgv[1], NULL, 0); |
| |
| if (g_ucMiracastMode == ucMode) { |
| /* XXX: continue or skip */ |
| } |
| |
| g_ucMiracastMode = ucMode; |
| prMsgWfdCfgUpdate = |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); |
| |
| if (prMsgWfdCfgUpdate != NULL) { |
| |
| prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); |
| prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; |
| prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; |
| |
| switch (ucMode) { |
| case MIRACAST_MODE_SOURCE: |
| prWfdCfgSettings->ucWfdEnable = 1; |
| snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1"); |
| break; |
| case MIRACAST_MODE_SINK: |
| prWfdCfgSettings->ucWfdEnable = 2; |
| snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2"); |
| break; |
| default: |
| prWfdCfgSettings->ucWfdEnable = 0; |
| snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); |
| break; |
| } |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); |
| |
| priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); |
| } /* prMsgWfdCfgUpdate */ |
| else { |
| DBGLOG(REQ, ERROR, ("%s: Memory alloc failed\n", __func__)); |
| i4BytesWritten = -1; |
| } |
| } |
| |
| /* i4Argc */ |
| return i4BytesWritten; |
| } |
| int |
| priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) |
| { |
| P_GLUE_INFO_T prGlueInfo = NULL; |
| int ret = 0; |
| char *pcCommand = NULL; |
| int i4BytesWritten = 0; |
| int i4TotalLen = 0; |
| priv_driver_cmd_t priv_cmd; |
| if (!prReq->ifr_data) { |
| ret = -EINVAL; |
| goto exit; |
| } |
| |
| prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); |
| ASSERT(prGlueInfo); |
| if (!prGlueInfo) { |
| DBGLOG(REQ, WARN, ("No glue info\n")); |
| ret = -EFAULT; |
| goto exit; |
| } |
| if (prGlueInfo->u4ReadyFlag == 0) { |
| ret = -EINVAL; |
| goto exit; |
| } |
| |
| if (copy_from_user(&priv_cmd, prReq->ifr_data, sizeof(priv_driver_cmd_t))) { |
| DBGLOG(REQ, INFO, ("%s: copy_from_user fail\n", __func__)); |
| ret = -EFAULT; |
| goto exit; |
| } |
| |
| i4TotalLen = priv_cmd.total_len; |
| |
| if (i4TotalLen <= 0) { |
| ret = -EINVAL; |
| goto exit; |
| } |
| |
| pcCommand = kmalloc(i4TotalLen, GFP_KERNEL); |
| if (!pcCommand) { |
| DBGLOG(REQ, INFO, |
| ("%s: failed to allocate memory size %d\n", __func__, i4TotalLen)); |
| ret = -ENOMEM; |
| goto exit; |
| } |
| |
| if (copy_from_user(pcCommand, priv_cmd.buf, i4TotalLen)) { |
| ret = -EFAULT; |
| goto exit; |
| } |
| |
| DBGLOG(REQ, INFO, |
| ("%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, prReq->ifr_name)); |
| |
| i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); |
| |
| if (i4BytesWritten < 0) { |
| DBGLOG(REQ, INFO, |
| ("%s: command %s Written is %d\n", __func__, pcCommand, i4BytesWritten)); |
| if (i4TotalLen >= 3) { |
| snprintf(pcCommand, 3, "OK\n"); |
| i4BytesWritten = strlen("OK\n"); |
| } |
| } else { |
| if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { |
| /* Reset the command buffers */ |
| pcCommand[0] = '\0'; |
| } |
| if (i4BytesWritten >= i4TotalLen) { |
| DBGLOG(REQ, INFO, |
| ("%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, |
| i4BytesWritten, i4TotalLen)); |
| i4BytesWritten = i4TotalLen; |
| } else { |
| pcCommand[i4BytesWritten] = '\0'; |
| i4BytesWritten++; |
| } |
| priv_cmd.used_len = i4BytesWritten; |
| if (copy_to_user(priv_cmd.buf, pcCommand, i4BytesWritten)) { |
| DBGLOG(REQ, WARN, ("failed to copy data to user buffer\n")); |
| ret = -EFAULT; |
| } |
| if (copy_to_user(prReq->ifr_data, &priv_cmd, sizeof(priv_driver_cmd_t))) { |
| DBGLOG(REQ, WARN, ("failed to copy driver_cmd to user buffer\n")); |
| ret = -EFAULT; |
| } |
| } |
| |
| exit: |
| if (pcCommand) { |
| kfree(pcCommand); |
| } |
| |
| return ret; |
| } |
| INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) |
| { |
| P_GLUE_INFO_T prGlueInfo = NULL; |
| INT_32 i4BytesWritten = 0; |
| if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) { |
| return -1; |
| } |
| prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); |
| |
| if (strnicmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) { |
| i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); |
| } else { |
| DBGLOG(REQ, INFO, ("Unknown driver command %s - ignored\n", pcCommand)); |
| return -1; |
| } |
| return i4BytesWritten; |
| } |