2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $
6 \brief This file including the protocol layer privacy function.
8 This file provided the macros and functions library support for the
9 protocol layer security setting from wlan_oid.c and for parse.c and
10 rsn.c and nic_privacy.c
21 * Fix compiling warning
24 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
25 * 1. eliminaite direct calls to printk in porting layer.
26 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
28 * 09 13 2011 jeffrey.chang
29 * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection
30 * fix the pointer casting
32 * 06 29 2011 george.huang
33 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
36 * 06 28 2011 george.huang
37 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
40 * 05 11 2011 jeffrey.chang
44 * 05 09 2011 jeffrey.chang
45 * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
46 * support ARP filter through kernel notifier
49 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
50 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
53 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
54 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
57 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
58 * improve portability for awareness of early version of linux kernel and wireless extension.
60 * 03 18 2011 jeffrey.chang
61 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
62 * remove early suspend functions
64 * 03 03 2011 jeffrey.chang
66 * add the ARP filter callback
68 * 02 15 2011 jeffrey.chang
70 * to support early suspend in android
73 * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 branch
74 * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/...
77 * [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
78 * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
79 * 2) Remove CNM CH-RECOVER event handling
80 * 3) cfg read/write API renamed with kal prefix for unified naming rules.
83 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
84 * complete implementation of Android NVRAM access
87 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check
88 * 1) add NVRAM access API
89 * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option)
90 * 3) add OID implementation for NVRAM read/write service
94 /*******************************************************************************
95 * C O M P I L E R F L A G S
96 ********************************************************************************
99 /*******************************************************************************
100 * E X T E R N A L R E F E R E N C E S
101 ********************************************************************************
103 #include <linux/version.h>
104 #include <linux/init.h>
105 #include <linux/types.h>
106 #include <linux/module.h>
107 #include <linux/fs.h>
109 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
110 #include <linux/uaccess.h>
116 #if defined(CONFIG_HAS_EARLY_SUSPEND)
117 #include <linux/earlysuspend.h>
122 extern BOOLEAN fgIsUnderEarlierSuspend;
124 /*******************************************************************************
126 ********************************************************************************
128 #define WIFI_NVRAM_FILE_NAME "/data/nvram/APCFG/APRDEB/WIFI"
129 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
132 /*******************************************************************************
134 ********************************************************************************
137 /*******************************************************************************
138 * P U B L I C D A T A
139 ********************************************************************************
142 /*******************************************************************************
143 * P R I V A T E D A T A
144 ********************************************************************************
147 /*******************************************************************************
149 ********************************************************************************
152 /*******************************************************************************
153 * F U N C T I O N D E C L A R A T I O N S
154 ********************************************************************************
157 /*******************************************************************************
159 ********************************************************************************
164 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
166 UINT_8 ip[4] = { 0 };
167 UINT_32 u4NumIPv4 = 0;
170 UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack
171 UINT_32 u4NumIPv6 = 0;
173 struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
174 struct net_device *prDev = ifa->ifa_dev->dev;
176 P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
177 P_GLUE_INFO_T prGlueInfo = NULL;
180 DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n"));
184 if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
185 DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
189 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
191 if (prGlueInfo == NULL) {
192 DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
197 if (fgIsUnderEarlierSuspend == false) {
198 DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
204 // <3> get the IPv4 address
205 if(!prDev || !(prDev->ip_ptr)||\
206 !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
207 !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
208 DBGLOG(REQ, INFO, ("ip is not avaliable.\n"));
212 kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
213 DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n",
214 ip[0],ip[1],ip[2],ip[3]));
216 // todo: traverse between list to find whole sets of IPv4 addresses
217 if (!((ip[0] == 0) &&
226 if(!prDev || !(prDev->ip6_ptr)||\
227 !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
228 !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
229 printk(KERN_INFO "ipv6 is not avaliable.\n");
233 kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
234 printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
235 ip6[0],ip6[1],ip6[2],ip6[3],
236 ip6[4],ip6[5],ip6[6],ip6[7],
237 ip6[8],ip6[9],ip6[10],ip6[11],
238 ip6[12],ip6[13],ip6[14],ip6[15]
241 // todo: traverse between list to find whole sets of IPv6 addresses
242 if (!((ip6[0] == 0) &&
252 // here we can compare the dev with other network's netdev to
253 // set the proper arp filter
255 // IMPORTANT: please make sure if the context can sleep, if the context can't sleep
256 // we should schedule a kernel thread to do this for us
258 // <7> set up the ARP filter
260 WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
261 UINT_32 u4SetInfoLen = 0;
262 UINT_8 aucBuf[32] = {0};
263 UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
264 P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf;
265 P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
269 prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
271 prParamNetAddrList->u4AddressCount = u4NumIPv4;
273 prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
274 for (i = 0; i < u4NumIPv4; i++) {
275 prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
276 prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
278 kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
279 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
280 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
282 prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
283 kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
284 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
285 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
290 for (i = 0; i < u4NumIPv6; i++) {
291 prParamNetAddr->u2AddressLength = 6;;
292 prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
293 kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
294 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));
295 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
298 ASSERT(u4Len <= sizeof(aucBuf));
300 DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
302 rStatus = kalIoctl(prGlueInfo,
303 wlanoidSetNetworkAddress,
304 (PVOID)prParamNetAddrList,
312 if (rStatus != WLAN_STATUS_SUCCESS) {
313 DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
321 static struct notifier_block inetaddr_notifier = {
322 .notifier_call = netdev_event,
325 void wlanRegisterNotifier(void)
327 register_inetaddr_notifier(&inetaddr_notifier);
330 //EXPORT_SYMBOL(wlanRegisterNotifier);
332 void wlanUnregisterNotifier(void)
334 unregister_inetaddr_notifier(&inetaddr_notifier);
337 //EXPORT_SYMBOL(wlanUnregisterNotifier);
340 #if defined(CONFIG_HAS_EARLYSUSPEND)
343 /*----------------------------------------------------------------------------*/
345 * \brief This function will register platform driver to os
347 * \param[in] wlanSuspend Function pointer to platform suspend function
348 * \param[in] wlanResume Function pointer to platform resume function
350 * \return The result of registering earlysuspend
352 /*----------------------------------------------------------------------------*/
354 int glRegisterEarlySuspend(
355 struct early_suspend *prDesc,
356 early_suspend_callback wlanSuspend,
357 late_resume_callback wlanResume)
361 if(NULL != wlanSuspend)
362 prDesc->suspend = wlanSuspend;
364 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
368 if(NULL != wlanResume)
369 prDesc->resume = wlanResume;
371 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
375 register_early_suspend(prDesc);
379 //EXPORT_SYMBOL(glRegisterEarlySuspend);
381 /*----------------------------------------------------------------------------*/
383 * \brief This function will un-register platform driver to os
385 * \return The result of un-registering earlysuspend
387 /*----------------------------------------------------------------------------*/
389 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
393 unregister_early_suspend(prDesc);
395 prDesc->suspend = NULL;
396 prDesc->resume = NULL;
401 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
403 #endif // !CONFIG_X86
405 /*----------------------------------------------------------------------------*/
407 * \brief Utility function for reading data from files on NVRAM-FS
416 * actual length of data being read
418 /*----------------------------------------------------------------------------*/
426 #if CFG_SUPPORT_NVRAM
430 mm_segment_t old_fs = get_fs();
433 fd = filp_open(filename, O_RDONLY, 0644);
436 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
441 if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
442 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
446 if (fd->f_pos != offset) {
447 if (fd->f_op->llseek) {
448 if(fd->f_op->llseek(fd, offset, 0) != offset) {
449 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to seek!!\n"));
458 retLen = fd->f_op->read(fd,
465 filp_close(fd, NULL);
471 #else // !CFG_SUPPORT_NVRAM
479 /*----------------------------------------------------------------------------*/
481 * \brief Utility function for writing data to files on NVRAM-FS
489 * actual length of data being written
491 /*----------------------------------------------------------------------------*/
499 #if CFG_SUPPORT_NVRAM
503 mm_segment_t old_fs = get_fs();
506 fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
509 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
514 if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
515 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
519 if (fd->f_pos != offset) {
520 if (fd->f_op->llseek) {
521 if(fd->f_op->llseek(fd, offset, 0) != offset) {
522 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to seek!!\n"));
531 retLen = fd->f_op->write(fd,
538 filp_close(fd, NULL);
544 #else // !CFG_SUPPORT_NVRAMS
552 /*----------------------------------------------------------------------------*/
554 * \brief API for reading data on NVRAM
565 /*----------------------------------------------------------------------------*/
568 IN P_GLUE_INFO_T prGlueInfo,
573 if(pu2Data == NULL) {
577 if(nvram_read(WIFI_NVRAM_FILE_NAME,
579 sizeof(unsigned short),
580 u4Offset) != sizeof(unsigned short)) {
589 /*----------------------------------------------------------------------------*/
591 * \brief API for writing data on NVRAM
601 /*----------------------------------------------------------------------------*/
604 IN P_GLUE_INFO_T prGlueInfo,
609 if(nvram_write(WIFI_NVRAM_FILE_NAME,
611 sizeof(unsigned short),
612 u4Offset) != sizeof(unsigned short)) {