--- /dev/null
+/*
+** $Id: @(#) gl_p2p.c@@
+*/
+
+/*! \file gl_p2p.c
+ \brief Main routines of Linux driver interface for Wi-Fi Direct
+
+ This file contains the main routines of Linux driver for MediaTek Inc. 802.11
+ Wireless LAN Adapters.
+*/
+
+
+
+/*
+** $Log: gl_p2p.c $
+**
+** 09 12 2012 wcpadmin
+** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages
+** .
+**
+** 08 17 2012 yuche.tsai
+** NULL
+** Fix compile warning.
+**
+** 08 16 2012 yuche.tsai
+** NULL
+** Fix compile warning.
+**
+** 08 14 2012 yuche.tsai
+** NULL
+** FPB from ALPS.JB to phase 2 release.
+**
+** 07 26 2012 yuche.tsai
+** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot
+** Update driver code of ALPS.JB for hot-spot.
+**
+** 07 19 2012 yuche.tsai
+** NULL
+** Code update for JB.
+ *
+ * 07 17 2012 yuche.tsai
+ * NULL
+ * Fix compile error for JB.
+ *
+ * 07 17 2012 yuche.tsai
+ * NULL
+ * Let netdev bring up.
+ *
+ * 07 17 2012 yuche.tsai
+ * NULL
+ * Compile no error before trial run.
+ *
+ * 01 09 2012 terry.wu
+ * [WCXRP00001166] [Wi-Fi] [Driver] cfg80211 integration for p2p newtork
+ * cfg80211 integration for p2p network.
+ *
+ * 12 19 2011 terry.wu
+ * [WCXRP00001142] [Wi-Fi] [P2P Driver] XOR local admin bit to generate p2p net device MAC
+ * XOR local administrated bit to generate net device MAC of p2p network.
+ *
+ * 12 02 2011 yuche.tsai
+ * NULL
+ * Fix possible KE when unload p2p.
+ *
+ * 11 24 2011 yuche.tsai
+ * NULL
+ * Fix P2P IOCTL of multicast address bug, add low power driver stop control.
+ *
+ * 11 22 2011 yuche.tsai
+ * NULL
+ * Update RSSI link quality of P2P Network query method. (Bug fix)
+ *
+ * 11 19 2011 yuche.tsai
+ * NULL
+ * Add RSSI support for P2P network.
+ *
+ * 11 16 2011 yuche.tsai
+ * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue.
+ * Avoid using work thread in set p2p multicast address callback.
+ *
+ * 11 11 2011 yuche.tsai
+ * NULL
+ * Fix work thread cancel issue.
+ *
+ * 11 11 2011 yuche.tsai
+ * NULL
+ * Fix default device name issue.
+ *
+ * 11 08 2011 yuche.tsai
+ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service discovery version check.
+ * Add support for driver version query & p2p supplicant verseion set.
+ * For new service discovery mechanism sync.
+ *
+ * 11 07 2011 yuche.tsai
+ * NULL
+ * [ALPS 00087243] KE in worker thread.
+ * The multicast address list is scheduled in worker thread.
+ * Before the worker thread is excuted, if P2P is unloaded, a KE may occur.
+ *
+ * 10 26 2011 terry.wu
+ * [WCXRP00001066] [MT6620 Wi-Fi] [P2P Driver] Fix P2P Oid Issue
+ * Fix some P2P OID functions didn't raise its flag "fgIsP2pOid" issue.
+ *
+ * 10 25 2011 cm.chang
+ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode
+ * .
+ *
+ * 10 18 2011 yuche.tsai
+ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch.
+ * Support Channle Query.
+ *
+ * 10 18 2011 yuche.tsai
+ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch.
+ * New 2.1 branch
+
+ *
+ * 08 26 2011 yuche.tsai
+ * NULL
+ * Fix bug of parsing secondary device list type issue.
+ *
+ * 08 24 2011 yuche.tsai
+ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature.
+ * Invitation Abort.
+ *
+ * 08 23 2011 yuche.tsai
+ * NULL
+ * Fix multicast address list issue of P2P.
+ *
+ * 08 22 2011 chinglan.wang
+ * NULL
+ * Fix invitation indication bug..
+ *
+ * 08 16 2011 cp.wu
+ * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence
+ * auto channel decision for 2.4GHz hot spot mode
+ *
+ * 08 16 2011 chinglan.wang
+ * NULL
+ * Add the group id information in the invitation indication.
+ *
+ * 08 09 2011 yuche.tsai
+ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature.
+ * Invitation Feature add on.
+ *
+ * 08 05 2011 yuche.tsai
+ * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution.
+ * Add Password ID check for quick connection.
+ * Also modify some connection policy.
+ *
+ * 07 18 2011 chinglan.wang
+ * NULL
+ * Add IOC_P2P_GO_WSC_IE (p2p capability).
+ *
+ * 06 14 2011 yuche.tsai
+ * NULL
+ * Add compile flag to disable persistent group support.
+ *
+ * 05 04 2011 chinglan.wang
+ * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver
+ * .
+ *
+ * 05 02 2011 yuche.tsai
+ * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout.
+ * Clear formation flag after formation timeout.
+ *
+ * 04 22 2011 george.huang
+ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode
+ * .
+ *
+ * 04 21 2011 george.huang
+ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode
+ * 1. Revise P2P power mode setting.
+ * 2. Revise fast-PS for concurrent
+ *
+ * 04 19 2011 wh.su
+ * NULL
+ * Adding length check before doing WPA RSN IE parsing for scan results indicate.
+ *
+ * 04 14 2011 yuche.tsai
+ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case.
+ * Connection flow refine for Sigma test.
+ *
+ * 04 08 2011 yuche.tsai
+ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO.
+ * Add device discoverability support.
+ *
+ * 04 08 2011 george.huang
+ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode
+ * separate settings of P2P and AIS
+ *
+ * 04 07 2011 terry.wu
+ * [WCXRP00000619] [MT6620 Wi-Fi][Driver] fix kernel panic may occur when removing wlan
+ * Fix kernel panic may occur when removing wlan driver.
+ *
+ * 03 31 2011 wh.su
+ * [WCXRP00000614] [MT6620 Wi-Fi][Driver] P2P: Update beacon content while setting WSC IE
+ * Update the wsc ie to beacon content.
+ *
+ * 03 25 2011 wh.su
+ * NULL
+ * add the sample code for set power mode and get power mode.
+ *
+ * 03 25 2011 yuche.tsai
+ * NULL
+ * Improve some error handleing.
+ *
+ * 03 22 2011 george.huang
+ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command
+ * link with supplicant commands
+ *
+ * 03 22 2011 yuche.tsai
+ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct.
+ * Modify formation policy.
+ *
+ * 03 22 2011 yuche.tsai
+ * NULL
+ * Modify formation policy setting.
+ *
+ * 03 18 2011 yuche.tsai
+ * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow
+ * Modify connection flow after Group Formation Complete, or device connect to a GO.
+ * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN.
+ *
+ * 03 15 2011 wh.su
+ * [WCXRP00000563] [MT6620 Wi-Fi] [P2P] Set local config method while set password Id ready
+ * set lccal config method method while set password Id ready.
+ *
+ * 03 15 2011 yuche.tsai
+ * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue
+ * Fix some configure method issue.
+ *
+ * 03 15 2011 jeffrey.chang
+ * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM
+ * refine queue_select function
+ *
+ * 03 13 2011 wh.su
+ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done
+ * add code for avoid compiling warning.
+ *
+ * 03 10 2011 yuche.tsai
+ * NULL
+ * Add P2P API.
+ *
+ * 03 10 2011 terry.wu
+ * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration
+ * Remove unnecessary assert and message.
+ *
+ * 03 08 2011 wh.su
+ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver
+ * support the power save related p2p setting.
+ *
+ * 03 07 2011 wh.su
+ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code
+ * rename the define to anti_pviracy.
+ *
+ * 03 05 2011 wh.su
+ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code
+ * add the code to get the check rsponse and indicate to app.
+ *
+ * 03 03 2011 jeffrey.chang
+ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
+ * support concurrent network
+ *
+ * 03 03 2011 jeffrey.chang
+ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
+ * modify P2P's netdevice functions to support multiple H/W queues
+ *
+ * 03 03 2011 cp.wu
+ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery
+ * for get request, the buffer length to be copied is header + payload.
+ *
+ * 03 02 2011 wh.su
+ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code
+ * add code to let the beacon and probe response for Auto GO WSC .
+ *
+ * 03 02 2011 cp.wu
+ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery
+ * add a missed break.
+ *
+ * 03 01 2011 yuche.tsai
+ * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation
+ * Update channel issue when doing GO formation..
+ *
+ * 02 25 2011 wh.su
+ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver
+ * add the Operation channel setting.
+ *
+ * 02 23 2011 wh.su
+ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver
+ * fixed the set int ioctl set index and value map to driver issue.
+ *
+ * 02 22 2011 wh.su
+ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver
+ * adding the ioctl set int from supplicant, and can used to set the p2p paramters
+ *
+ * 02 21 2011 terry.wu
+ * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P
+ * Clean P2P scan list while removing P2P.
+ *
+ * 02 18 2011 wh.su
+ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE
+ * fixed the ioctl setting that index not map to spec defined config method.
+ *
+ * 02 17 2011 wh.su
+ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE
+ * append the WSC IE config method attribute at provision discovery request.
+ *
+ * 02 17 2011 wh.su
+ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request
+ * modify the structure pointer for set WSC IE.
+ *
+ * 02 16 2011 wh.su
+ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request
+ * fixed the probe request send out without WSC IE issue (at P2P).
+ *
+ * 02 09 2011 cp.wu
+ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery
+ * fix typo
+ *
+ * 02 09 2011 yuche.tsai
+ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode.
+ * Add Support for MLME deauthentication for Hot-Spot.
+ *
+ * 01 25 2011 terry.wu
+ * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter
+ * Add a new module parameter to indicate current runnig mode, P2P or AP.
+ *
+ * 01 12 2011 yuche.tsai
+ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue
+ * 1. Modify Channel Acquire Time of AP mode from 5s to 1s.
+ * 2. Call cnmP2pIsPermit() before active P2P network.
+ * 3. Add channel selection support for AP mode.
+ *
+ * 01 05 2011 cp.wu
+ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery
+ * ioctl implementations for P2P Service Discovery
+ *
+ * 01 04 2011 cp.wu
+ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
+ *
+ * 12 22 2010 cp.wu
+ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service Discovery
+ * 1. header file restructure for more clear module isolation
+ * 2. add function interface definition for implementing Service Discovery callbacks
+ *
+ * 12 15 2010 cp.wu
+ * NULL
+ * invoke nicEnableInterrupt() before leaving from wlanAdapterStart()
+ *
+ * 12 08 2010 yuche.tsai
+ * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in
+ * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add
+ *
+ * 11 30 2010 yuche.tsai
+ * NULL
+ * Invitation & Provision Discovery Indication.
+ *
+ * 11 17 2010 wh.su
+ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx lowest rate at wlan table for normal operation
+ * fixed some ASSERT check.
+ *
+ * 11 04 2010 wh.su
+ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID
+ * adding the p2p random ssid support.
+ *
+ * 10 20 2010 wh.su
+ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group
+ * Add the code to support disconnect p2p group
+ *
+ * 10 04 2010 wh.su
+ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P
+ * add a kal function for set cipher.
+ *
+ * 10 04 2010 wh.su
+ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P
+ * fixed compiling error while enable p2p.
+ *
+ * 09 28 2010 wh.su
+ * NULL
+ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo.
+ *
+ * 09 21 2010 kevin.huang
+ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface
+ * Isolate P2P related function for Hardware Software Bundle
+ *
+ * 09 21 2010 kevin.huang
+ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
+ * Eliminate Linux Compile Warning
+ *
+ * 09 10 2010 george.huang
+ * NULL
+ * update iwpriv LP related
+ *
+ * 09 10 2010 wh.su
+ * NULL
+ * fixed the compiling error at win XP.
+ *
+ * 09 09 2010 cp.wu
+ * NULL
+ * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result.
+ *
+ * 09 07 2010 wh.su
+ * NULL
+ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p.
+ *
+ * 09 06 2010 wh.su
+ * NULL
+ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state.
+ *
+ * 08 25 2010 cp.wu
+ * NULL
+ * add netdev_ops(NDO) for linux kernel 2.6.31 or greater
+ *
+ * 08 23 2010 cp.wu
+ * NULL
+ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated)
+ *
+ * 08 20 2010 cp.wu
+ * NULL
+ * correct typo.
+ *
+ * 08 20 2010 yuche.tsai
+ * NULL
+ * Invert Connection request provision status parameter.
+ *
+ * 08 19 2010 cp.wu
+ * NULL
+ * add set mac address interface for further possibilities of wpa_supplicant overriding interface address.
+ *
+ * 08 18 2010 cp.wu
+ * NULL
+ * modify pwp ioctls attribution by removing FIXED_SIZE.
+ *
+ * 08 18 2010 jeffrey.chang
+ * NULL
+ * support multi-function sdio
+ *
+ * 08 17 2010 cp.wu
+ * NULL
+ * correct p2p net device registration with NULL pointer access issue.
+ *
+ * 08 16 2010 cp.wu
+ * NULL
+ * P2P packets are now marked when being queued into driver, and identified later without checking MAC address
+ *
+ * 08 16 2010 cp.wu
+ * NULL
+ * add subroutines for P2P to set multicast list.
+ *
+ * 08 16 2010 george.huang
+ * NULL
+ * add wext handlers to link P2P set PS profile/ network address function (TBD)
+ *
+ * 08 16 2010 cp.wu
+ * NULL
+ * revised implementation of Wi-Fi Direct io controls.
+ *
+ * 08 12 2010 cp.wu
+ * NULL
+ * follow-up with ioctl interface update for Wi-Fi Direct application
+ *
+ * 08 06 2010 cp.wu
+ * NULL
+ * driver hook modifications corresponding to ioctl interface change.
+ *
+ * 08 03 2010 cp.wu
+ * NULL
+ * add basic support for ioctl of getting scan result. (only address and SSID are reporterd though)
+ *
+ * 08 03 2010 cp.wu
+ * NULL
+ * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant
+ *
+ * 08 03 2010 cp.wu
+ * NULL
+ * surpress compilation warning.
+ *
+ * 08 03 2010 cp.wu
+ * NULL
+ * [Wi-Fi Direct] add framework for driver hooks
+ *
+ * 07 08 2010 cp.wu
+ *
+ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
+ *
+ * 06 23 2010 cp.wu
+ * [WPD00003833][MT6620 and MT5931] Driver migration
+ * p2p interface revised to be sync. with HAL
+ *
+ * 06 06 2010 kevin.huang
+ * [WPD00003832][MT6620 5931] Create driver base
+ * [MT6620 5931] Create driver base
+ *
+ * 06 01 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add ioctl to configure scan mode for p2p connection
+ *
+ * 05 31 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add cfg80211 interface, which is to replace WE, for further extension
+ *
+ * 05 17 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * implement private io controls for Wi-Fi Direct
+ *
+ * 05 17 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * implement get scan result.
+ *
+ * 05 17 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add basic handling framework for wireless extension ioctls.
+ *
+ * 05 17 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * 1) add timeout handler mechanism for pending command packets
+ * 2) add p2p add/removal key
+ *
+ * 05 14 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * implement wireless extension ioctls in iw_handler form.
+ *
+ * 05 14 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well
+ *
+ * 05 11 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * p2p ioctls revised.
+ *
+ * 05 11 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add ioctl for controlling p2p scan phase parameters
+ *
+ * 05 10 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * implement basic wi-fi direct framework
+ *
+ * 05 07 2010 cp.wu
+ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
+ * add basic framework for implementating P2P driver hook.
+ *
+**
+*/
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+#include "gl_os.h"
+#include "debug.h"
+#include "wlan_lib.h"
+#include "gl_wext.h"
+#include <linux/poll.h>
+
+#include <linux/kmod.h>
+/* #include <net/cfg80211.h> */
+#include "gl_p2p_ioctl.h"
+
+#include "precomp.h"
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+#define ARGV_MAX_NUM (4)
+
+/*For CFG80211 - wiphy parameters*/
+#define MAX_SCAN_LIST_NUM (1)
+#define MAX_SCAN_IE_LEN (512)
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+/* for cfg80211 - frequency table */
+static struct ieee80211_channel mtk_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel mtk_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(149, 0),
+ CHAN5G(153, 0), CHAN5G(157, 0),
+ CHAN5G(161, 0), CHAN5G(165, 0),
+ CHAN5G(169, 0), CHAN5G(173, 0),
+ CHAN5G(184, 0), CHAN5G(188, 0),
+ CHAN5G(192, 0), CHAN5G(196, 0),
+ CHAN5G(200, 0), CHAN5G(204, 0),
+ CHAN5G(208, 0), CHAN5G(212, 0),
+ CHAN5G(216, 0),
+};
+
+/* for cfg80211 - rate table */
+static struct ieee80211_rate mtk_rates[] = {
+ RATETAB_ENT(10, 0x1000, 0),
+ RATETAB_ENT(20, 0x1001, 0),
+ RATETAB_ENT(55, 0x1002, 0),
+ RATETAB_ENT(110, 0x1003, 0), /* 802.11b */
+ RATETAB_ENT(60, 0x2000, 0),
+ RATETAB_ENT(90, 0x2001, 0),
+ RATETAB_ENT(120, 0x2002, 0),
+ RATETAB_ENT(180, 0x2003, 0),
+ RATETAB_ENT(240, 0x2004, 0),
+ RATETAB_ENT(360, 0x2005, 0),
+ RATETAB_ENT(480, 0x2006, 0),
+ RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */
+};
+
+#define mtk_a_rates (mtk_rates + 4)
+#define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4)
+#define mtk_g_rates (mtk_rates + 0)
+#define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0)
+
+#define MT6620_MCS_INFO \
+{ \
+ /* MCS1~7*/ \
+ .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
+ .rx_highest = 0, \
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
+}
+
+#if 0
+/*Bandwidth 20Mhz Only*/
+#define MT6620_HT_CAP \
+{ \
+ .ht_supported = true, \
+ .cap = IEEE80211_HT_CAP_SM_PS \
+ | IEEE80211_HT_CAP_GRN_FLD \
+ | IEEE80211_HT_CAP_SGI_20, \
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \
+ .mcs = MT6620_MCS_INFO, \
+}
+#else
+/*Bandwidth 20/40Mhz*/
+#define MT6620_HT_CAP \
+{ \
+ .ht_supported = true, \
+ .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \
+ | IEEE80211_HT_CAP_SM_PS \
+ | IEEE80211_HT_CAP_GRN_FLD \
+ | IEEE80211_HT_CAP_SGI_20 \
+ | IEEE80211_HT_CAP_SGI_40, \
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \
+ .mcs = MT6620_MCS_INFO, \
+}
+#endif
+
+static struct ieee80211_supported_band mtk_band_2ghz = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = mtk_2ghz_channels,
+ .n_channels = ARRAY_SIZE(mtk_2ghz_channels),
+ .bitrates = mtk_g_rates,
+ .n_bitrates = mtk_g_rates_size,
+ .ht_cap = MT6620_HT_CAP,
+};
+
+static struct ieee80211_supported_band mtk_band_5ghz = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = mtk_5ghz_a_channels,
+ .n_channels = ARRAY_SIZE(mtk_5ghz_a_channels),
+ .bitrates = mtk_a_rates,
+ .n_bitrates = mtk_a_rates_size,
+ .ht_cap = MT6620_HT_CAP,
+};
+
+static const UINT_32 cipher_suites[] = {
+ /* keep WEP first, it may be removed below */
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+
+ /* keep last -- depends on hw flags! */
+ WLAN_CIPHER_SUITE_AES_CMAC
+};
+
+static struct cfg80211_ops mtk_p2p_config_ops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0)
+ /* Froyo */
+ .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1 st */
+ .change_bss = mtk_p2p_cfg80211_change_bss,
+ .scan = mtk_p2p_cfg80211_scan,
+ .remain_on_channel = mtk_p2p_cfg80211_remain_on_channel,
+ .cancel_remain_on_channel = mtk_p2p_cfg80211_cancel_remain_on_channel,
+ .mgmt_tx = mtk_p2p_cfg80211_mgmt_tx,
+ .connect = mtk_p2p_cfg80211_connect,
+ .disconnect = mtk_p2p_cfg80211_disconnect,
+ .deauth = mtk_p2p_cfg80211_deauth,
+ .disassoc = mtk_p2p_cfg80211_disassoc,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ .start_ap = mtk_p2p_cfg80211_start_ap,
+ .change_beacon = mtk_p2p_cfg80211_change_beacon,
+ .stop_ap = mtk_p2p_cfg80211_stop_ap,
+#else
+ .add_beacon = mtk_p2p_cfg80211_add_set_beacon,
+ .set_beacon = mtk_p2p_cfg80211_add_set_beacon,
+ .del_beacon = mtk_p2p_cfg80211_stop_ap,
+#endif
+ .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params,
+ .del_station = mtk_p2p_cfg80211_del_station,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ .set_monitor_channel = mtk_p2p_cfg80211_set_channel,
+#else
+ .set_channel = mtk_p2p_cfg80211_set_channel,
+#endif
+ .set_bitrate_mask = mtk_p2p_cfg80211_set_bitrate_mask,
+ .mgmt_frame_register = mtk_p2p_cfg80211_mgmt_frame_register,
+ .get_station = mtk_p2p_cfg80211_get_station,
+ /* ================ */
+ .add_key = mtk_p2p_cfg80211_add_key,
+ .get_key = mtk_p2p_cfg80211_get_key,
+ .del_key = mtk_p2p_cfg80211_del_key,
+ .set_default_key = mtk_p2p_cfg80211_set_default_key,
+ .join_ibss = mtk_p2p_cfg80211_join_ibss,
+ .leave_ibss = mtk_p2p_cfg80211_leave_ibss,
+ .set_tx_power = mtk_p2p_cfg80211_set_txpower,
+ .get_tx_power = mtk_p2p_cfg80211_get_txpower,
+ .set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt,
+#ifdef CONFIG_NL80211_TESTMODE
+ .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd,
+#endif
+#endif
+};
+
+
+
+/* There isn't a lot of sense in it, but you can transmit anything you like */
+static const struct ieee80211_txrx_stypes
+ mtk_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_ADHOC] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_AP_VLAN] = {
+ /* copy AP */
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ }
+};
+
+
+
+#endif
+
+/* the legacy wireless extension stuff */
+static const iw_handler rP2PIwStandardHandler[] = {
+ [SIOCGIWPRIV - SIOCIWFIRST] = mtk_p2p_wext_get_priv,
+ [SIOCGIWSCAN - SIOCIWFIRST] = mtk_p2p_wext_discovery_results,
+ [SIOCSIWESSID - SIOCIWFIRST] = mtk_p2p_wext_reconnect,
+ [SIOCSIWAUTH - SIOCIWFIRST] = mtk_p2p_wext_set_auth,
+ [SIOCSIWENCODEEXT - SIOCIWFIRST] = mtk_p2p_wext_set_key,
+ [SIOCSIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_set_powermode,
+ [SIOCGIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_get_powermode,
+ [SIOCSIWTXPOW - SIOCIWFIRST] = mtk_p2p_wext_set_txpow,
+#if CFG_SUPPORT_P2P_RSSI_QUERY
+ [SIOCGIWSTATS - SIOCIWFIRST] = mtk_p2p_wext_get_rssi,
+#endif
+ [SIOCSIWMLME - SIOCIWFIRST] = mtk_p2p_wext_mlme_handler,
+};
+
+static const iw_handler rP2PIwPrivHandler[] = {
+ [IOC_P2P_CFG_DEVICE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_local_dev_info,
+ [IOC_P2P_PROVISION_COMPLETE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_provision_complete,
+ [IOC_P2P_START_STOP_DISCOVERY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_start_stop_discovery,
+ [IOC_P2P_DISCOVERY_RESULTS - SIOCIWFIRSTPRIV] = mtk_p2p_wext_discovery_results,
+ [IOC_P2P_WSC_BEACON_PROBE_RSP_IE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_wsc_ie,
+ [IOC_P2P_CONNECT_DISCONNECT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_connect_disconnect,
+ [IOC_P2P_PASSWORD_READY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_password_ready,
+/* [IOC_P2P_SET_PWR_MGMT_PARAM - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_pm_param, */
+ [IOC_P2P_SET_INT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_int,
+ [IOC_P2P_GET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_get_struct,
+ [IOC_P2P_SET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_struct,
+ [IOC_P2P_GET_REQ_DEVICE_INFO - SIOCIWFIRSTPRIV] = mtk_p2p_wext_request_dev_info,
+};
+
+
+static const struct iw_priv_args rP2PIwPrivTable[] = {
+ {
+ .cmd = IOC_P2P_CFG_DEVICE,
+ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CFG_DEVICE_TYPE),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_CFG_DEVICE"}
+ ,
+ {
+ .cmd = IOC_P2P_START_STOP_DISCOVERY,
+ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_REQ_DEVICE_TYPE),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_DISCOVERY"}
+ ,
+ {
+ .cmd = IOC_P2P_DISCOVERY_RESULTS,
+ .set_args = IW_PRIV_TYPE_NONE,
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_RESULT"}
+ ,
+ {
+ .cmd = IOC_P2P_WSC_BEACON_PROBE_RSP_IE,
+ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_HOSTAPD_PARAM),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_WSC_IE"}
+ ,
+ {
+ .cmd = IOC_P2P_CONNECT_DISCONNECT,
+ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CONNECT_DEVICE),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_CONNECT"}
+ ,
+ {
+ .cmd = IOC_P2P_PASSWORD_READY,
+ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_PASSWORD_READY),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_PASSWD_RDY"}
+ ,
+ {
+ .cmd = IOC_P2P_GET_STRUCT,
+ .set_args = IW_PRIV_TYPE_NONE,
+ .get_args = 256,
+ .name = "P2P_GET_STRUCT"}
+ ,
+ {
+ .cmd = IOC_P2P_SET_STRUCT,
+ .set_args = 256,
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "P2P_SET_STRUCT"}
+ ,
+ {
+ .cmd = IOC_P2P_GET_REQ_DEVICE_INFO,
+ .set_args = IW_PRIV_TYPE_NONE,
+ .get_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_DEVICE_REQ),
+ .name = "P2P_GET_REQDEV"}
+ ,
+ {
+ /* SET STRUCT sub-ioctls commands */
+ .cmd = PRIV_CMD_OID,
+ .set_args = 256,
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "set_oid"}
+ ,
+ {
+ /* GET STRUCT sub-ioctls commands */
+ .cmd = PRIV_CMD_OID,
+ .set_args = IW_PRIV_TYPE_NONE,
+ .get_args = 256,
+ .name = "get_oid"}
+};
+
+const struct iw_handler_def mtk_p2p_wext_handler_def = {
+ .num_standard = (__u16) sizeof(rP2PIwStandardHandler) / sizeof(iw_handler),
+ .num_private = (__u16) sizeof(rP2PIwPrivHandler) / sizeof(iw_handler),
+ .num_private_args = (__u16) sizeof(rP2PIwPrivTable) / sizeof(struct iw_priv_args),
+ .standard = rP2PIwStandardHandler,
+ .private = rP2PIwPrivHandler,
+ .private_args = rP2PIwPrivTable,
+#if CFG_SUPPORT_P2P_RSSI_QUERY
+ .get_wireless_stats = mtk_p2p_wext_get_wireless_stats,
+#else
+ .get_wireless_stats = NULL,
+#endif
+};
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support p2p_wowlan_support = {
+ .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY,
+};
+#endif
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+/* for IE Searching */
+extern BOOLEAN
+wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart,
+ IN INT_32 i4TotalIeLen,
+ IN UINT_8 ucDesiredElemId, OUT PUINT_8 * ppucDesiredIE);
+
+#if CFG_SUPPORT_WPS
+extern BOOLEAN
+wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart,
+ IN INT_32 i4TotalIeLen,
+ IN UINT_8 ucDesiredElemId, OUT PUINT_8 * ppucDesiredIE);
+#endif
+
+/* Net Device Hooks */
+static int p2pOpen(IN struct net_device *prDev);
+
+static int p2pStop(IN struct net_device *prDev);
+
+static struct net_device_stats *p2pGetStats(IN struct net_device *prDev);
+
+static void p2pSetMulticastList(IN struct net_device *prDev);
+
+static int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev);
+
+static int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIFReq, int i4Cmd);
+
+static int p2pSetMACAddress(IN struct net_device *prDev, void *addr);
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Override the implementation of select queue
+*
+* \param[in] dev Pointer to struct net_device
+* \param[in] skb Pointer to struct skb_buff
+*
+* \return (none)
+*/
+/*----------------------------------------------------------------------------*/
+
+unsigned int _p2p_cfg80211_classify8021d(struct sk_buff *skb)
+{
+ unsigned int dscp = 0;
+
+ /* skb->priority values from 256->263 are magic values
+ * directly indicate a specific 802.1d priority. This is
+ * to allow 802.1d priority to be passed directly in from
+ * tags
+ */
+
+ if (skb->priority >= 256 && skb->priority <= 263) {
+ return skb->priority - 256;
+ }
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ dscp = ip_hdr(skb)->tos & 0xfc;
+ break;
+ }
+ return dscp >> 5;
+}
+
+
+static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+
+static UINT_16 p2pSelectQueue(struct net_device *dev, struct sk_buff *skb)
+{
+ skb->priority = _p2p_cfg80211_classify8021d(skb);
+
+ return au16Wlan1dToQueueIdx[skb->priority];
+}
+
+static struct net_device *g_P2pPrDev;
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief A function for prDev->init
+*
+* \param[in] prDev Pointer to struct net_device.
+*
+* \retval 0 The execution of wlanInit succeeds.
+* \retval -ENXIO No such device.
+*/
+/*----------------------------------------------------------------------------*/
+static int p2pInit(struct net_device *prDev)
+{
+ if (!prDev) {
+ return -ENXIO;
+ }
+
+ return 0; /* success */
+} /* end of p2pInit() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief A function for prDev->uninit
+*
+* \param[in] prDev Pointer to struct net_device.
+*
+* \return (none)
+*/
+/*----------------------------------------------------------------------------*/
+static void p2pUninit(IN struct net_device *prDev)
+{
+
+
+ return;
+} /* end of p2pUninit() */
+
+
+
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+static const struct net_device_ops p2p_netdev_ops = {
+ .ndo_open = p2pOpen,
+ .ndo_stop = p2pStop,
+ .ndo_set_mac_address = p2pSetMACAddress,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ .ndo_set_rx_mode = p2pSetMulticastList,
+#else
+ .ndo_set_multicast_list = p2pSetMulticastList,
+#endif
+ .ndo_get_stats = p2pGetStats,
+ .ndo_do_ioctl = p2pDoIOCTL,
+ .ndo_start_xmit = p2pHardStartXmit,
+ .ndo_select_queue = p2pSelectQueue,
+ .ndo_init = p2pInit,
+ .ndo_uninit = p2pUninit,
+};
+
+
+#endif
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS
+* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_WIFI_VAR_T prWifiVar = NULL;
+
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ prWifiVar = &(prAdapter->rWifiVar);
+
+ ASSERT(prAdapter);
+ ASSERT(prWifiVar);
+
+ do {
+ if (prGlueInfo == NULL) {
+ break;
+ }
+
+ if (prGlueInfo->prP2PInfo == NULL) {
+ /*alloc memory for p2p info */
+ prGlueInfo->prP2PInfo = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE);
+ prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE);
+ prWifiVar->prP2PConnSettings =
+ kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE);
+ prWifiVar->prP2pFsmInfo = kalMemAlloc(sizeof(P2P_FSM_INFO_T), VIR_MEM_TYPE);
+ prWifiVar->prP2pSpecificBssInfo =
+ kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE);
+ } else {
+ ASSERT(prAdapter->prP2pInfo != NULL);
+ ASSERT(prWifiVar->prP2PConnSettings != NULL);
+ ASSERT(prWifiVar->prP2pFsmInfo != NULL);
+ ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL);
+ }
+ /*MUST set memory to 0 */
+ kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T));
+ kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T));
+ kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T));
+ kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T));
+ kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T));
+
+ } while (FALSE);
+
+
+ /* chk if alloc successful or not */
+ if (prGlueInfo->prP2PInfo &&
+ prAdapter->prP2pInfo &&
+ prWifiVar->prP2PConnSettings &&
+ prWifiVar->prP2pFsmInfo && prWifiVar->prP2pSpecificBssInfo) {
+ return TRUE;
+ } else {
+
+ if (prWifiVar->prP2pSpecificBssInfo) {
+ kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE,
+ sizeof(P2P_SPECIFIC_BSS_INFO_T));
+
+ prWifiVar->prP2pSpecificBssInfo = NULL;
+ }
+ if (prWifiVar->prP2pFsmInfo) {
+ kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T));
+
+ prWifiVar->prP2pFsmInfo = NULL;
+ }
+ if (prWifiVar->prP2PConnSettings) {
+ kalMemFree(prWifiVar->prP2PConnSettings, VIR_MEM_TYPE,
+ sizeof(P2P_CONNECTION_SETTINGS_T));
+
+ prWifiVar->prP2PConnSettings = NULL;
+ }
+ if (prGlueInfo->prP2PInfo) {
+ kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T));
+
+ prGlueInfo->prP2PInfo = NULL;
+ }
+ if (prAdapter->prP2pInfo) {
+ kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T));
+
+ prAdapter->prP2pInfo = NULL;
+ }
+ return FALSE;
+ }
+
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Free memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS
+* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo)
+{
+
+ ASSERT(prGlueInfo);
+ ASSERT(prGlueInfo->prAdapter);
+
+ /* free memory after p2p module is ALREADY unregistered */
+ if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) {
+
+ kalMemFree(prGlueInfo->prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T));
+ kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T));
+ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings, VIR_MEM_TYPE,
+ sizeof(P2P_CONNECTION_SETTINGS_T));
+ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE,
+ sizeof(P2P_FSM_INFO_T));
+ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo, VIR_MEM_TYPE,
+ sizeof(P2P_SPECIFIC_BSS_INFO_T));
+
+ /*Reomve p2p bss scan list */
+ scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter);
+
+ /*reset all pointer to NULL */
+ prGlueInfo->prP2PInfo = NULL;
+ prGlueInfo->prAdapter->prP2pInfo = NULL;
+ prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings = NULL;
+ prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL;
+ prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo = NULL;
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Enable Channel for cfg80211 for Wi-Fi Direct based on current country code
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+p2pEnableChannel(PUINT_8 pucChIdx,
+ UINT_8 ucChannelNum,
+ struct ieee80211_channel *mtk_channels, UINT_8 mtk_channel_sz)
+{
+ UINT_8 ucCurChIdx = *pucChIdx;
+
+ while (TRUE) {
+ (*pucChIdx)++;
+ (*pucChIdx) %= mtk_channel_sz;
+
+ if (ucChannelNum == mtk_channels[*pucChIdx].hw_value) {
+ mtk_channels[*pucChIdx].flags &= ~IEEE80211_CHAN_DISABLED;
+ break;
+ }
+
+ if (*pucChIdx == ucCurChIdx) {
+ printk(KERN_ALERT DRV_NAME "Orphan channel [%d]\n", ucChannelNum);
+ break;
+ }
+ }
+}
+
+
+BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired)
+{
+ BOOLEAN fgDoRegister = FALSE;
+ BOOLEAN ret;
+
+ GLUE_SPIN_LOCK_DECLARATION();
+
+ ASSERT(prGlueInfo);
+ ASSERT(prGlueInfo->prAdapter);
+
+
+ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+ if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) {
+ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERING;
+ fgDoRegister = TRUE;
+ }
+ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+
+ if (!fgDoRegister) {
+ return TRUE;
+ }
+
+ /* Here are functions which need rtnl_lock */
+ wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy);
+
+ /* net device initialize */
+ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+ /* register for net device */
+ if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) {
+ printk(KERN_ALERT DRV_NAME "unable to register netdevice for p2p\n");
+
+ free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+
+ ret = FALSE;
+ } else {
+ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED;
+ ret = TRUE;
+ }
+ return ret;
+}
+
+BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired)
+{
+ BOOLEAN fgDoUnregister = FALSE;
+
+ GLUE_SPIN_LOCK_DECLARATION();
+
+ ASSERT(prGlueInfo);
+ ASSERT(prGlueInfo->prAdapter);
+
+ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+ if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) {
+ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING;
+ fgDoUnregister = TRUE;
+ }
+ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+
+ if (!fgDoUnregister) {
+ return TRUE;
+ }
+
+ /* prepare for removal */
+ if (netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) {
+ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+ }
+
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+ DBGLOG(P2P, INFO, ("P2P unregister_netdev 0x%p\n", prGlueInfo->prP2PInfo->prDevHandler));
+ unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+
+ wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy);
+ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED;
+
+ return TRUE;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+VOID p2pUpdateChannelTableByDomain(P_GLUE_INFO_T prGlueInfo)
+{
+ UINT_8 i, uc2gChIdx, uc5gChIdx;
+ UINT_8 ucMaxChannelNum = ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_a_channels);
+ UINT_8 ucNumOfChannel = ucMaxChannelNum;
+ RF_CHANNEL_INFO_T aucChannelList[ucMaxChannelNum];
+
+ uc2gChIdx = uc5gChIdx = 0;
+
+ /* 1. Disable all channel */
+ for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) {
+ mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+ }
+ for (i = 0; i < ARRAY_SIZE(mtk_5ghz_a_channels); i++) {
+ mtk_5ghz_a_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+ }
+
+ /* 2. Get current domain channel list */
+ rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_NULL, ucMaxChannelNum, &ucNumOfChannel,
+ aucChannelList);
+
+ /* 3. Enable specific channel based on domain channel list */
+ for (i = 0; i < ucNumOfChannel; i++) {
+ switch (aucChannelList[i].eBand) {
+ case BAND_2G4:
+ p2pEnableChannel(&uc2gChIdx, aucChannelList[i].ucChannelNum,
+ mtk_2ghz_channels, ARRAY_SIZE(mtk_2ghz_channels));
+ break;
+
+ case BAND_5G:
+ p2pEnableChannel(&uc5gChIdx, aucChannelList[i].ucChannelNum,
+ mtk_5ghz_a_channels, ARRAY_SIZE(mtk_5ghz_a_channels));
+ break;
+
+ default:
+ printk(KERN_ALERT DRV_NAME "Unknow band.\n");
+ break;
+
+ }
+ }
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Register for cfg80211 for Wi-Fi Direct
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GL_HIF_INFO_T prHif = NULL;
+ PARAM_MAC_ADDRESS rMacAddr;
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+ struct device *prDev;
+#endif
+
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prHif = &prGlueInfo->rHifInfo;
+ ASSERT(prHif);
+
+ printk("glRegisterP2P\n");
+
+ /*0. allocate p2pinfo */
+ if (!p2PAllocInfo(prGlueInfo)) {
+ printk(KERN_ALERT DRV_NAME "Allocate memory for p2p FAILED\n");
+ ASSERT(0);
+ return FALSE;
+ }
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+ /* 1. allocate WIPHY */
+ prGlueInfo->prP2PInfo->wdev.wiphy = wiphy_new(&mtk_p2p_config_ops, sizeof(P_GLUE_INFO_T));
+ if (!prGlueInfo->prP2PInfo->wdev.wiphy) {
+ printk(KERN_ALERT DRV_NAME "unable to allocate wiphy for p2p\n");
+
+ goto err_alloc_wiphy;
+ }
+
+ /* 1.1 fill wiphy parameters */
+#if MTK_WCN_HIF_SDIO
+ mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev);
+ if (!prDev) {
+ printk(KERN_ALERT DRV_NAME "unable to get struct dev for p2p\n");
+ }
+#else
+ prDev = &(prHif->func->dev);
+#endif
+ set_wiphy_dev(prGlueInfo->prP2PInfo->wdev.wiphy, prDev);
+
+ prGlueInfo->prP2PInfo->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_AP)
+ | BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO)
+ | BIT(NL80211_IFTYPE_STATION);
+
+ p2pUpdateChannelTableByDomain(prGlueInfo);
+ prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz;
+ if (prAdapter->fgEnable5GBand) {
+ prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
+ }
+
+ prGlueInfo->prP2PInfo->wdev.wiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes;
+ prGlueInfo->prP2PInfo->wdev.wiphy->max_remain_on_channel_duration = 5000;
+ prGlueInfo->prP2PInfo->wdev.wiphy->n_cipher_suites = 5;
+ prGlueInfo->prP2PInfo->wdev.wiphy->cipher_suites = (const u32 *)cipher_suites;
+ prGlueInfo->prP2PInfo->wdev.wiphy->flags =
+ WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+ WIPHY_FLAG_HAVE_AP_SME;
+ prGlueInfo->prP2PInfo->wdev.wiphy->ap_sme_capa = 1;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+ prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ssids = MAX_SCAN_LIST_NUM;
+ prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ie_len = MAX_SCAN_IE_LEN;
+ prGlueInfo->prP2PInfo->wdev.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+#endif
+
+#ifdef CONFIG_PM
+ kalMemCopy(&(prGlueInfo->prP2PInfo->wdev.wiphy->wowlan),
+ &p2p_wowlan_support, sizeof(struct wiphy_wowlan_support));
+#endif
+#if 0
+ /* 2. Register WIPHY */
+ if (wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy) < 0) {
+ printk(KERN_ALERT DRV_NAME "Couldn't register wiphy device for p2p\n");
+
+ goto err_reg_wiphy;
+ }
+#endif
+
+ /* 2.1 set priv as pointer to glue structure */
+ *((P_GLUE_INFO_T *) wiphy_priv(prGlueInfo->prP2PInfo->wdev.wiphy)) = prGlueInfo;
+
+ /* 2.2 wdev initialization */
+ if (fgIsApMode) {
+ prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_AP;
+ } else {
+ prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
+ }
+
+#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */
+
+ /* 3. allocate netdev */
+ prGlueInfo->prP2PInfo->prDevHandler =
+ alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM);
+ if (!prGlueInfo->prP2PInfo->prDevHandler) {
+ printk(KERN_ALERT DRV_NAME "unable to allocate netdevice for p2p\n");
+
+ printk("unable to allocate netdevice for p2p\n");
+
+ goto err_alloc_netdev;
+ }
+
+ /* 4. setup netdev */
+ /* 4.1 Point to shared glue structure */
+ *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo;
+
+ /* 4.2 fill hardware address */
+ COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr);
+ rMacAddr[0] ^= 0x2; /* change to local administrated address */
+ memcpy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr, ETH_ALEN);
+ memcpy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr,
+ prGlueInfo->prP2PInfo->prDevHandler->dev_addr, ETH_ALEN);
+
+ /* 4.3 register callback functions */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+ prGlueInfo->prP2PInfo->prDevHandler->netdev_ops = &p2p_netdev_ops;
+#else
+ prGlueInfo->prP2PInfo->prDevHandler->open = p2pOpen;
+ prGlueInfo->prP2PInfo->prDevHandler->stop = p2pStop;
+ prGlueInfo->prP2PInfo->prDevHandler->get_stats = p2pGetStats;
+ prGlueInfo->prP2PInfo->prDevHandler->set_multicast_list = p2pSetMulticastList;
+ prGlueInfo->prP2PInfo->prDevHandler->hard_start_xmit = p2pHardStartXmit;
+ prGlueInfo->prP2PInfo->prDevHandler->do_ioctl = p2pDoIOCTL;
+ prGlueInfo->prP2PInfo->prDevHandler->set_mac_address = p2pSetMACAddress;
+#endif
+/* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */
+
+
+#if (MTK_WCN_HIF_SDIO == 0)
+ SET_NETDEV_DEV(prGlueInfo->prP2PInfo->prDevHandler, &(prHif->func->dev));
+#endif
+
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+ prGlueInfo->prP2PInfo->prDevHandler->ieee80211_ptr = &(prGlueInfo->prP2PInfo->wdev);
+ prGlueInfo->prP2PInfo->wdev.netdev = prGlueInfo->prP2PInfo->prDevHandler;
+#endif
+
+#if CFG_TCP_IP_CHKSUM_OFFLOAD
+ prGlueInfo->prP2PInfo->prDevHandler->features = NETIF_F_IP_CSUM;
+#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
+
+#if 0
+ /* 7. net device initialize */
+ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+ /* 8. register for net device */
+ if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) {
+ printk(KERN_ALERT DRV_NAME "unable to register netdevice for p2p\n");
+
+ goto err_reg_netdev;
+ }
+#endif
+
+ /* 8. set p2p net device register state */
+ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED;
+
+ /* 9. setup running mode */
+ prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode;
+
+ /* 10. finish */
+ p2pFsmInit(prAdapter);
+
+ p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings);
+
+ /* Active network too early would cause HW not able to sleep.
+ * Defer the network active time.
+ */
+/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */
+
+ return TRUE;
+#if 0
+ err_reg_netdev:
+ free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+#endif
+ err_alloc_netdev:
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+/* wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy); */
+
+/* err_reg_wiphy: */
+ wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy);
+ prGlueInfo->prP2PInfo->wdev.wiphy = NULL;
+
+ err_alloc_wiphy:
+#endif
+
+ return FALSE;
+} /* end of glRegisterP2P() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Unregister Net Device for Wi-Fi Direct
+*
+* \param[in] prGlueInfo Pointer to glue info
+*
+* \return TRUE
+* FALSE
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo)
+{
+ ASSERT(prGlueInfo);
+
+ p2pFsmUninit(prGlueInfo->prAdapter);
+
+ nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+
+#if 0
+ /* Release command, mgmt and security frame belong to P2P network in
+ * prGlueInfo->prCmdQue
+ * prAdapter->rPendingCmdQueue
+ * prAdapter->rTxCtrl.rTxMgmtTxingQueue
+ * To ensure there is no pending CmdDone/TxDone handler to be executed after p2p module is removed.
+ */
+
+ /* Clear CmdQue */
+ kalClearMgmtFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX);
+ kalClearSecurityFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX);
+ /* Clear PendingCmdQue */
+ wlanReleasePendingCMDbyNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+ /* Clear PendingTxMsdu */
+ nicFreePendingTxMsduInfoByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+#endif
+
+#if 0
+ /* prepare for removal */
+ if (netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) {
+ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+ }
+
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+ /* netdevice unregistration & free */
+ unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+#endif
+ free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+ prGlueInfo->prP2PInfo->prDevHandler = NULL;
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+#if 0
+ wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy);
+#endif
+ wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy);
+ prGlueInfo->prP2PInfo->wdev.wiphy = NULL;
+#endif
+
+ /* Free p2p memory */
+#if 1
+ if (!p2PFreeInfo(prGlueInfo)) {
+ printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n");
+ ASSERT(0);
+ return FALSE;
+ }
+#endif
+ return TRUE;
+
+} /* end of glUnregisterP2P() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief A function for stop p2p fsm immediate
+ *
+ * \param[in] prGlueInfo Pointer to struct P_GLUE_INFO_T.
+ *
+ * \retval TRUE The execution succeeds.
+ * \retval FALSE The execution failed.
+ */
+/*----------------------------------------------------------------------------*/
+BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo)
+{
+/* P_ADAPTER_T prAdapter = NULL; */
+/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */
+
+ ASSERT(prGlueInfo);
+
+/* prAdapter = prGlueInfo->prAdapter; */
+/* ASSERT(prAdapter); */
+
+ /* 1. stop TX queue */
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+
+#if 0
+ /* 2. switch P2P-FSM off */
+ /* 2.1 allocate for message */
+ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof(MSG_P2P_FUNCTION_SWITCH_T));
+
+ if (!prFuncSwitch) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ printk(KERN_ALERT DRV_NAME "Allocate for p2p mesasage FAILED\n");
+ /* return -ENOMEM; */
+ }
+
+ /* 2.2 fill message */
+ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH;
+ prFuncSwitch->fgIsFuncOn = FALSE;
+
+ /* 2.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_UNBUF);
+
+#endif
+
+ /* 3. stop queue and turn off carrier */
+ prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED;
+
+ return TRUE;
+} /* end of p2pStop() */
+
+
+/* Net Device Hooks */
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief A function for net_device open (ifup)
+ *
+ * \param[in] prDev Pointer to struct net_device.
+ *
+ * \retval 0 The execution succeeds.
+ * \retval < 0 The execution failed.
+ */
+/*----------------------------------------------------------------------------*/
+static int p2pOpen(IN struct net_device *prDev)
+{
+/* P_GLUE_INFO_T prGlueInfo = NULL; */
+/* P_ADAPTER_T prAdapter = NULL; */
+/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */
+
+ ASSERT(prDev);
+
+#if 0 /* Move after device name set. (mtk_p2p_set_local_dev_info) */
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* 1. switch P2P-FSM on */
+ /* 1.1 allocate for message */
+ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof(MSG_P2P_FUNCTION_SWITCH_T));
+
+ if (!prFuncSwitch) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ /* 1.2 fill message */
+ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH;
+ prFuncSwitch->fgIsFuncOn = TRUE;
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF);
+#endif
+
+ /* 2. carrier on & start TX queue */
+ netif_carrier_on(prDev);
+ netif_tx_start_all_queues(prDev);
+
+ return 0; /* success */
+} /* end of p2pOpen() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief A function for net_device stop (ifdown)
+ *
+ * \param[in] prDev Pointer to struct net_device.
+ *
+ * \retval 0 The execution succeeds.
+ * \retval < 0 The execution failed.
+ */
+/*----------------------------------------------------------------------------*/
+static int p2pStop(IN struct net_device *prDev)
+{
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ /* P_ADAPTER_T prAdapter = NULL; */
+/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */
+ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL;
+
+ struct cfg80211_scan_request *prScanRequest = NULL;
+ GLUE_SPIN_LOCK_DECLARATION();
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prGlueP2pInfo = prGlueInfo->prP2PInfo;
+ ASSERT(prGlueP2pInfo);
+
+ /* CFG80211 down */
+ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+ if (prGlueP2pInfo->prScanRequest != NULL) {
+ prScanRequest = prGlueP2pInfo->prScanRequest;
+ prGlueP2pInfo->prScanRequest = NULL;
+ }
+ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
+
+ if (prScanRequest) {
+ cfg80211_scan_done(prScanRequest, TRUE);
+ }
+#if 0
+
+ /* 1. stop TX queue */
+ netif_tx_stop_all_queues(prDev);
+
+ /* 2. switch P2P-FSM off */
+ /* 2.1 allocate for message */
+ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof(MSG_P2P_FUNCTION_SWITCH_T));
+
+ if (!prFuncSwitch) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ /* 2.2 fill message */
+ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH;
+ prFuncSwitch->fgIsFuncOn = FALSE;
+
+ /* 2.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF);
+#endif
+ /* 3. stop queue and turn off carrier */
+ prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED;
+
+ netif_tx_stop_all_queues(prDev);
+ if (netif_carrier_ok(prDev)) {
+ netif_carrier_off(prDev);
+ }
+
+ return 0;
+} /* end of p2pStop() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief A method of struct net_device, to get the network interface statistical
+ * information.
+ *
+ * Whenever an application needs to get statistics for the interface, this method
+ * is called. This happens, for example, when ifconfig or netstat -i is run.
+ *
+ * \param[in] prDev Pointer to struct net_device.
+ *
+ * \return net_device_stats buffer pointer.
+ */
+/*----------------------------------------------------------------------------*/
+struct net_device_stats *p2pGetStats(IN struct net_device *prDev)
+{
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+#if 0 /* frog temp fix */
+ /* @FIXME */
+ /* prDev->stats.rx_packets = 0; */
+ /* prDev->stats.tx_packets = 0; */
+ prDev->stats.tx_errors = 0;
+ prDev->stats.rx_errors = 0;
+ /* prDev->stats.rx_bytes = 0; */
+ /* prDev->stats.tx_bytes = 0; */
+ prDev->stats.multicast = 0;
+
+ return &prDev->stats;
+
+#else
+ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_packets = 0; */
+ /* prGlueInfo->prP2PInfo->rNetDevStats.tx_packets = 0; */
+ prGlueInfo->prP2PInfo->rNetDevStats.tx_errors = 0;
+ prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0;
+ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes = 0; */
+ /* prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes = 0; */
+ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; */
+ prGlueInfo->prP2PInfo->rNetDevStats.multicast = 0;
+
+ return &prGlueInfo->prP2PInfo->rNetDevStats;
+#endif
+} /* end of p2pGetStats() */
+
+
+
+
+static void p2pSetMulticastList(IN struct net_device *prDev)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+
+ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL;
+
+ ASSERT(prDev);
+ ASSERT(prGlueInfo);
+ if (!prDev || !prGlueInfo) {
+ printk(KERN_WARNING DRV_NAME
+ " abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo);
+ return;
+ }
+
+
+ g_P2pPrDev = prDev;
+
+ /* 4 Mark HALT, notify main thread to finish current job */
+ prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_MULTICAST;
+ /* wake up main thread */
+ wake_up_interruptible(&prGlueInfo->waitq);
+
+} /* p2pSetMulticastList */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief This function is to set multicast list and set rx mode.
+ *
+ * \param[in] prDev Pointer to struct net_device
+ *
+ * \return (none)
+ */
+/*----------------------------------------------------------------------------*/
+void mtk_p2p_wext_set_Multicastlist(P_GLUE_INFO_T prGlueInfo)
+{
+ UINT_32 u4SetInfoLen = 0;
+ struct net_device *prDev = g_P2pPrDev;
+
+ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL;
+
+ ASSERT(prDev);
+ ASSERT(prGlueInfo);
+ if (!prDev || !prGlueInfo) {
+ printk(KERN_WARNING DRV_NAME
+ " abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo);
+ return;
+ }
+
+
+ if (prDev->flags & IFF_PROMISC) {
+ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS;
+ }
+
+ if (prDev->flags & IFF_BROADCAST) {
+ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST;
+ }
+
+ if (prDev->flags & IFF_MULTICAST) {
+ if ((prDev->flags & IFF_ALLMULTI) ||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) {
+#else
+ (prDev->mc_count > MAX_NUM_GROUP_ADDR)) {
+#endif
+ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST;
+ }
+ else {
+ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST;
+ }
+ }
+
+ if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) {
+ /* Prepare multicast address list */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ struct netdev_hw_addr *ha;
+#else
+ struct dev_mc_list *prMcList;
+#endif
+ UINT_32 i = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ netdev_for_each_mc_addr(ha, prDev) {
+ if (i < MAX_NUM_GROUP_ADDR) {
+ COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr);
+ i++;
+ }
+ }
+#else
+ for (i = 0, prMcList = prDev->mc_list;
+ (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR);
+ i++, prMcList = prMcList->next) {
+ COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]),
+ prMcList->dmi_addr);
+ }
+#endif
+
+ DBGLOG(P2P, TRACE, ("SEt Multicast Address List\n"));
+
+ if (i >= MAX_NUM_GROUP_ADDR) {
+ return;
+ }
+ wlanoidSetP2PMulticastList(prGlueInfo->prAdapter,
+ &(prGlueInfo->prP2PInfo->aucMCAddrList[0]),
+ (i * ETH_ALEN), &u4SetInfoLen);
+
+ }
+
+ return;
+} /* end of p2pSetMulticastList() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * * \brief This function is TX entry point of NET DEVICE.
+ * *
+ * * \param[in] prSkb Pointer of the sk_buff to be sent
+ * * \param[in] prDev Pointer to struct net_device
+ * *
+ * * \retval NETDEV_TX_OK - on success.
+ * * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer.
+ * */
+/*----------------------------------------------------------------------------*/
+int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev)
+{
+ P_QUE_ENTRY_T prQueueEntry = NULL;
+ P_QUE_T prTxQueue = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ UINT_16 u2QueueIdx = 0;
+
+ GLUE_SPIN_LOCK_DECLARATION();
+
+ ASSERT(prSkb);
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+ if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+ printk(KERN_INFO DRV_NAME "GLUE_FLAG_HALT skip tx\n");
+ dev_kfree_skb(prSkb);
+ return NETDEV_TX_OK;
+ }
+ /* mark as P2P packets */
+ GLUE_SET_PKT_FLAG_P2P(prSkb);
+#if CFG_ENABLE_PKT_LIFETIME_PROFILE
+ GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick());
+#endif
+
+ prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb);
+ prTxQueue = &prGlueInfo->rTxQueue;
+
+ if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) {
+
+ u2QueueIdx = skb_get_queue_mapping(prSkb);
+ ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM);
+
+ if (u2QueueIdx >= CFG_MAX_TXQ_NUM) {
+ printk(KERN_INFO DRV_NAME "Incorrect queue index, skip this frame\n");
+ dev_kfree_skb(prSkb);
+ return NETDEV_TX_OK;
+ }
+ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
+ QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry);
+ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
+
+ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum);
+ GLUE_INC_REF_CNT(prGlueInfo->
+ ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]);
+
+ if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx] >=
+ CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) {
+ netif_stop_subqueue(prDev, u2QueueIdx);
+ }
+ } else {
+ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum);
+ }
+
+ kalSetEvent(prGlueInfo);
+
+ /* Statistic usage. */
+ prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes += prSkb->len;
+ prGlueInfo->prP2PInfo->rNetDevStats.tx_packets++;
+ /* prDev->stats.tx_packets++; */
+
+ return NETDEV_TX_OK;
+} /* end of p2pHardStartXmit() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief A method of struct net_device, a primary SOCKET interface to configure
+ * the interface lively. Handle an ioctl call on one of our devices.
+ * Everything Linux ioctl specific is done here. Then we pass the contents
+ * of the ifr->data to the request message handler.
+ *
+ * \param[in] prDev Linux kernel netdevice
+ *
+ * \param[in] prIFReq Our private ioctl request structure, typed for the generic
+ * struct ifreq so we can use ptr to function
+ *
+ * \param[in] cmd Command ID
+ *
+ * \retval WLAN_STATUS_SUCCESS The IOCTL command is executed successfully.
+ * \retval OTHER The execution of IOCTL command is failed.
+ */
+/*----------------------------------------------------------------------------*/
+int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIFReq, int i4Cmd)
+{
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ int ret = 0;
+ char *prExtraBuf = NULL;
+ UINT_32 u4ExtraSize = 0;
+ struct iwreq *prIwReq = (struct iwreq *)prIFReq;
+ struct iw_request_info rIwReqInfo;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+ if (prGlueInfo->u4ReadyFlag == 0) {
+ /* adapter not ready yet */
+ return -EINVAL;
+ }
+ /* fill rIwReqInfo */
+ rIwReqInfo.cmd = (__u16) i4Cmd;
+ rIwReqInfo.flags = 0;
+
+ switch (i4Cmd) {
+ case SIOCSIWENCODEEXT:
+ /* Set Encryption Material after 4-way handshaking is done */
+ if (prIwReq->u.encoding.pointer) {
+ u4ExtraSize = prIwReq->u.encoding.length;
+ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+
+ if (!prExtraBuf) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(prExtraBuf,
+ prIwReq->u.encoding.pointer,
+ prIwReq->u.encoding.length)) {
+ ret = -EFAULT;
+ }
+ } else if (prIwReq->u.encoding.length != 0) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret == 0) {
+ ret = mtk_p2p_wext_set_key(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf);
+ }
+
+ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+ prExtraBuf = NULL;
+ break;
+
+ case SIOCSIWMLME:
+ /* IW_MLME_DISASSOC used for disconnection */
+ if (prIwReq->u.data.length != sizeof(struct iw_mlme)) {
+ printk(KERN_INFO "MLME buffer strange:%d\n", prIwReq->u.data.length);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!prIwReq->u.data.pointer) {
+ ret = -EINVAL;
+ break;
+ }
+
+ prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE);
+ if (!prExtraBuf) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(prExtraBuf, prIwReq->u.data.pointer, sizeof(struct iw_mlme))) {
+ ret = -EFAULT;
+ } else {
+ ret =
+ mtk_p2p_wext_mlme_handler(prDev, &rIwReqInfo, &(prIwReq->u),
+ prExtraBuf);
+ }
+
+ kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme));
+ prExtraBuf = NULL;
+ break;
+
+ case SIOCGIWPRIV:
+ /* This ioctl is used to list all IW privilege ioctls */
+ ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL);
+ break;
+
+ case SIOCGIWSCAN:
+ ret = mtk_p2p_wext_discovery_results(prDev, &rIwReqInfo, &(prIwReq->u), NULL);
+ break;
+
+ case SIOCSIWAUTH:
+ ret = mtk_p2p_wext_set_auth(prDev, &rIwReqInfo, &(prIwReq->u), NULL);
+ break;
+
+ case IOC_P2P_CFG_DEVICE:
+ case IOC_P2P_PROVISION_COMPLETE:
+ case IOC_P2P_START_STOP_DISCOVERY:
+ case IOC_P2P_DISCOVERY_RESULTS:
+ case IOC_P2P_WSC_BEACON_PROBE_RSP_IE:
+ case IOC_P2P_CONNECT_DISCONNECT:
+ case IOC_P2P_PASSWORD_READY:
+ case IOC_P2P_GET_STRUCT:
+ case IOC_P2P_SET_STRUCT:
+ case IOC_P2P_GET_REQ_DEVICE_INFO:
+ ret =
+ rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV] (prDev, &rIwReqInfo, &(prIwReq->u),
+ (char *)&(prIwReq->u));
+ break;
+#if CFG_SUPPORT_P2P_RSSI_QUERY
+ case SIOCGIWSTATS:
+ ret = mtk_p2p_wext_get_rssi(prDev, &rIwReqInfo, &(prIwReq->u), NULL);
+ break;
+#endif
+ default:
+ ret = -ENOTTY;
+ }
+
+ return ret;
+} /* end of p2pDoIOCTL() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief To report the private supported IOCTLs table to user space.
+ *
+ * \param[in] prDev Net device requested.
+ * \param[out] prIfReq Pointer to ifreq structure, content is copied back to
+ * user space buffer in gl_iwpriv_table.
+ *
+ * \retval 0 For success.
+ * \retval -E2BIG For user's buffer size is too small.
+ * \retval -EFAULT For fail.
+ *
+ */
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_priv(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ UINT_16 u2BufferSize = 0;
+
+ ASSERT(prDev);
+
+ u2BufferSize = prData->length;
+
+ /* update our private table size */
+ prData->length = (__u16) sizeof(rP2PIwPrivTable) / sizeof(struct iw_priv_args);
+
+ if (u2BufferSize < prData->length) {
+ return -E2BIG;
+ }
+
+ if (prData->length) {
+ if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) {
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+} /* end of mtk_p2p_wext_get_priv() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief To indicate P2P-FSM for re-associate to the connecting device
+ *
+ * \param[in] prDev Net device requested.
+ * \param[inout] wrqu Pointer to iwreq_data
+ *
+ * \retval 0 For success.
+ * \retval -EFAULT For fail.
+ *
+ */
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_reconnect(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+#if 0
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_MSG_HDR_T prMsgHdr;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T));
+ if (!prMsgHdr) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ /* 1.2 fill message */
+
+ DBGLOG(P2P, TRACE, ("mtk_p2p_wext_reconnect: P2P Reconnect\n"));
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF);
+#endif
+ return 0;
+} /* end of mtk_p2p_wext_reconnect() */
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief MLME command handler
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_mlme_handler(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+#if 0
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T) NULL;
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]);
+
+ DBGLOG(P2P, TRACE, ("mtk_p2p_wext_mlme_handler:\n"));
+
+ switch (mlme->cmd) {
+ case IW_MLME_DISASSOC:
+ prMsgP2PConnAbt =
+ (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof(MSG_P2P_CONNECTION_ABORT_T));
+ if (!prMsgP2PConnAbt) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data);
+
+ prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code;
+
+
+ if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) {
+ DBGLOG(P2P, TRACE, ("P2P Connection Abort:\n"));
+
+ /* 1.2 fill message */
+ prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT;
+ } else {
+ DBGLOG(P2P, TRACE, ("P2P Connection Pause:\n"));
+
+ /* 1.2 fill message */
+ }
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF);
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+#endif
+ return 0;
+} /* end of mtk_p2p_wext_mlme_handler() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+#if 0
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ P_MSG_HDR_T prMsgHdr;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ switch (prData->flags) {
+ case P2P_PROVISIONING_SUCCESS:
+ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T));
+ if (!prMsgHdr) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ /* 1.2 fill message */
+
+ prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP;
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF);
+
+ break;
+
+ case P2P_PROVISIONING_FAIL:
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+#endif
+
+ return 0;
+} /* end of mtk_p2p_wext_set_provision_complete() */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+#if 0
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra;
+ UINT_8 au4IeBuf[MAX_IE_LENGTH];
+ P_MSG_HDR_T prMsgHdr;
+ P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg;
+ P_P2P_CONNECTION_SETTINGS_T prConnSettings;
+ UINT_8 aucNullAddr[] = NULL_MAC_ADDR;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings;
+
+ if (prData->flags == P2P_STOP_DISCOVERY) {
+ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T));
+
+ if (!prMsgHdr) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF);
+ } else if (prData->flags == P2P_START_DISCOVERY) {
+
+ /* retrieve IE for Probe Response */
+ if (prReqDeviceType->probe_rsp_len > 0) {
+ if (prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) {
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[2],
+ prReqDeviceType->probe_rsp_ie,
+ prReqDeviceType->probe_rsp_len)) {
+ return -EFAULT;
+ }
+ prGlueInfo->prP2PInfo->u2WSCIELen[2] =
+ prReqDeviceType->probe_rsp_len;
+ } else {
+ return -E2BIG;
+ }
+ }
+
+ /* retrieve IE for Probe Request */
+ if (prReqDeviceType->probe_req_len > 0) {
+ if (prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) {
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[1],
+ prReqDeviceType->probe_req_ie,
+ prReqDeviceType->probe_req_len)) {
+ return -EFAULT;
+ }
+ prGlueInfo->prP2PInfo->u2WSCIELen[1] =
+ prReqDeviceType->probe_req_len;
+ } else {
+ return -E2BIG;
+ }
+ }
+ /* update IE for Probe Request */
+
+ if (prReqDeviceType->scan_type == P2P_LISTEN) {
+ /* update listening parameter */
+
+ /* @TODO: update prConnSettings for Probe Response IE */
+ } else {
+ /* indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY */
+ prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof
+ (MSG_P2P_DEVICE_DISCOVER_T));
+
+ if (!prDiscoverMsg) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY;
+ prDiscoverMsg->u4DevDiscoverTime = 0; /* unlimited */
+ prDiscoverMsg->fgIsSpecificType = TRUE;
+ prDiscoverMsg->rTargetDeviceType.u2CategoryID =
+ *(PUINT_16) (&(prReqDeviceType->pri_device_type[0]));
+ prDiscoverMsg->rTargetDeviceType.u2SubCategoryID =
+ *(PUINT_16) (&(prReqDeviceType->pri_device_type[6]));
+ COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr);
+
+ /* @FIXME: parameter to be refined, where to pass IE buffer ? */
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prDiscoverMsg, MSG_SEND_METHOD_BUF);
+ }
+ } else {
+ return -EINVAL;
+ }
+#endif
+
+ return 0;
+} /* end of mtk_p2p_wext_start_stop_discovery() */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Setting parameters not support.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_invitation_request(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int i4Status = 0;
+#if 0
+ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL;
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation =
+ (P_IW_P2P_IOCTL_INVITATION_STRUCT) NULL;
+
+ do {
+ if ((prDev == NULL) || (extra == NULL)) {
+ ASSERT(FALSE);
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) extra;
+
+ if (prGlueInfo == NULL) {
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prAdapter = prGlueInfo->prAdapter;
+
+ if (prAdapter == NULL) {
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ if (prIoctlInvitation->ucReinvoke == 1) {
+ /* TODO: Set Group ID */
+ p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID,
+ prIoctlInvitation->aucSsid, prIoctlInvitation->u4SsidLen);
+ }
+
+ else {
+ P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq =
+ (P_MSG_P2P_INVITATION_REQUEST_T) NULL;
+
+ /* TODO: Do Invitation. */
+ prMsgP2PInvitationReq =
+ (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof
+ (MSG_P2P_INVITATION_REQUEST_T));
+ if (!prMsgP2PInvitationReq) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ i4Status = -ENOMEM;
+ break;
+ }
+
+ /* 1.2 fill message */
+ kalMemCopy(prMsgP2PInvitationReq->aucDeviceID,
+ prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN);
+
+ DBGLOG(P2P, TRACE,
+ ("mtk_p2p_wext_invitation_request: P2P Invitation Req\n"));
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0,
+ (P_MSG_HDR_T) prMsgP2PInvitationReq, MSG_SEND_METHOD_BUF);
+
+ }
+
+
+
+ } while (FALSE);
+#endif
+
+ return i4Status;
+
+}
+
+/* mtk_p2p_wext_invitation_request */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Setting parameters not support.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_invitation_abort(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int i4Status = 0;
+#if 0
+ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL;
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort =
+ (P_IW_P2P_IOCTL_ABORT_INVITATION) NULL;
+
+ UINT_8 bssid[MAC_ADDR_LEN];
+
+ do {
+ if ((prDev == NULL) || (extra == NULL)) {
+ ASSERT(FALSE);
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) extra;
+
+ if (prGlueInfo == NULL) {
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prAdapter = prGlueInfo->prAdapter;
+
+ if (prAdapter == NULL) {
+ i4Status = -EINVAL;
+ break;
+ } else {
+ P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationAbort =
+ (P_MSG_P2P_INVITATION_REQUEST_T) NULL;
+
+ prMsgP2PInvitationAbort =
+ (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof
+ (MSG_P2P_INVITATION_REQUEST_T));
+
+ if (!prMsgP2PInvitationAbort) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ i4Status = -ENOMEM;
+ break;
+ }
+
+
+ /* 1.2 fill message */
+ kalMemCopy(prMsgP2PInvitationAbort->aucDeviceID,
+ prIoctlInvitationAbort->dev_addr, MAC_ADDR_LEN);
+
+ DBGLOG(P2P, TRACE,
+ ("mtk_p2p_wext_invitation_request: P2P Invitation Req\n"));
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0,
+ (P_MSG_HDR_T) prMsgP2PInvitationAbort, MSG_SEND_METHOD_BUF);
+
+ }
+
+
+ } while (FALSE);
+#endif
+
+ return i4Status;
+
+}
+
+/* mtk_p2p_wext_invitation_abort */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief To override p2p interface address
+ *
+ * \param[in] prDev Net device requested.
+ * \param[in] addr Pointer to address
+ *
+ * \retval 0 For success.
+ * \retval -E2BIG For user's buffer size is too small.
+ * \retval -EFAULT For fail.
+ *
+ */
+/*----------------------------------------------------------------------------*/
+int p2pSetMACAddress(IN struct net_device *prDev, void *addr)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* @FIXME */
+ return eth_mac_addr(prDev, addr);
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set encryption cipher suite
+*
+* \param[in] prDev Net device requested.
+* \param[out]
+*
+* \retval 0 Success.
+* \retval -EINVAL Invalid parameter
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_auth(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_param *prAuth = (struct iw_param *)wrqu;
+
+ ASSERT(prDev);
+ ASSERT(prAuth);
+ if (FALSE == GLUE_CHK_PR2(prDev, prAuth)) {
+ return -EINVAL;
+ }
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+ /* Save information to glue info and process later when ssid is set. */
+ switch (prAuth->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ break;
+ case IW_AUTH_CIPHER_PAIRWISE:
+ prGlueInfo->prP2PInfo->u4CipherPairwise = prAuth->value;
+ break;
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ case IW_AUTH_DROP_UNENCRYPTED:
+ case IW_AUTH_80211_AUTH_ALG:
+ case IW_AUTH_WPA_ENABLED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_ROAMING_CONTROL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ default:
+ /* @TODO */
+ break;
+ }
+
+ return 0;
+} /* end of mtk_p2p_wext_set_auth() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set encryption cipher and key.
+*
+* \param[in] prDev Net device requested.
+* \param[out] prIfReq Pointer to ifreq structure, content is copied back to
+* user space buffer in gl_iwpriv_table.
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note Securiry information is stored in pEnc.
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_key(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int ret = 0;
+ struct iw_encode_ext *prIWEncExt;
+ struct iw_point *prEnc;
+ char *prExtraBuf = NULL;
+ UINT_32 u4ExtraSize = 0;
+ UINT_8 keyStructBuf[100];
+ P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf;
+ P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf;
+ P_GLUE_INFO_T prGlueInfo;
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4BufLen = 0;
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+ do {
+ if (wrqu->encoding.pointer) {
+ u4ExtraSize = wrqu->encoding.length;
+ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+
+ if (!prExtraBuf) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(prExtraBuf,
+ wrqu->encoding.pointer, wrqu->encoding.length)) {
+ ret = -EFAULT;
+ break;
+ }
+ } else if (wrqu->encoding.length != 0) {
+ ret = -EINVAL;
+ break;
+ }
+
+ prEnc = &wrqu->encoding;
+ prIWEncExt = (struct iw_encode_ext *)prExtraBuf;
+
+ if (GLUE_CHK_PR3(prDev, prEnc, prExtraBuf) == TRUE) {
+ memset(keyStructBuf, 0, sizeof(keyStructBuf));
+
+ if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { /* Key Removal */
+ prRemoveKey->u4Length = sizeof(*prRemoveKey);
+ memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetRemoveP2PKey,
+ prRemoveKey,
+ prRemoveKey->u4Length,
+ FALSE, FALSE, TRUE, TRUE, &u4BufLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS)
+ ret = -EFAULT;
+ } else {
+ if (prIWEncExt->alg == IW_ENCODE_ALG_CCMP) {
+ /* KeyID */
+ prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
+ ((prEnc->flags & IW_ENCODE_INDEX) - 1) : 0;
+ if (prKey->u4KeyIndex <= 3) {
+ /* bit(31) and bit(30) are shared by pKey and pRemoveKey */
+ /* Tx Key Bit(31) */
+ if (prIWEncExt->
+ ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ prKey->u4KeyIndex |= 0x1UL << 31;
+ }
+
+ /* Pairwise Key Bit(30) */
+ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /* group key */
+ } else {
+ /* pairwise key */
+ prKey->u4KeyIndex |= 0x1UL << 30;
+ }
+
+ /* Rx SC Bit(29) */
+ if (prIWEncExt->
+ ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+ prKey->u4KeyIndex |= 0x1UL << 29;
+ memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq,
+ IW_ENCODE_SEQ_MAX_SIZE);
+ }
+
+ /* BSSID */
+ memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6);
+ memcpy(prKey->aucKeyMaterial, prIWEncExt->key,
+ prIWEncExt->key_len);
+
+ prKey->u4KeyLength = prIWEncExt->key_len;
+ prKey->u4Length =
+ ((UINT_32) &
+ (((P_PARAM_KEY_T) 0)->aucKeyMaterial)) +
+ prKey->u4KeyLength;
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetAddP2PKey,
+ prKey,
+ prKey->u4Length,
+ FALSE,
+ FALSE, TRUE, TRUE, &u4BufLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ ret = -EFAULT;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ }
+ } else
+ ret = -EINVAL;
+
+ } while (FALSE);
+
+ if (prExtraBuf) {
+ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+ prExtraBuf = NULL;
+ }
+
+ return ret;
+} /* end of mtk_p2p_wext_set_key() */
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief set the p2p gc power mode
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_powermode(IN struct net_device *prNetDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ /* printk("set_powermode = %d, value = %d\n", wrqu->power.disabled, wrqu->power.value); */
+ struct iw_param *prPower = (struct iw_param *)&wrqu->power;
+#if 1
+ PARAM_POWER_MODE ePowerMode;
+ INT_32 i4PowerValue;
+
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4BufLen = 0;
+
+ ASSERT(prNetDev);
+ ASSERT(prPower);
+ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
+ return -EINVAL;
+ }
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+ /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */
+ /* prPower->value, prPower->disabled, prPower->flags); */
+
+ if (prPower->disabled) {
+ ePowerMode = Param_PowerModeCAM;
+ } else {
+ i4PowerValue = prPower->value;
+#if WIRELESS_EXT < 21
+ i4PowerValue /= 1000000;
+#endif
+ if (i4PowerValue == 0) {
+ ePowerMode = Param_PowerModeCAM;
+ } else if (i4PowerValue == 1) {
+ ePowerMode = Param_PowerModeMAX_PSP;
+ } else if (i4PowerValue == 2) {
+ ePowerMode = Param_PowerModeFast_PSP;
+ } else {
+ printk(KERN_DEBUG "%s(): unsupported power management mode value = %d.\n",
+ __func__, prPower->value);
+
+ return -EINVAL;
+ }
+ }
+
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetP2pPowerSaveProfile,
+ &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, TRUE, &u4BufLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */
+ return -EFAULT;
+ }
+#endif
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief get the p2p gc power mode
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_powermode(IN struct net_device *prNetDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ /* printk("mtk_p2p_wext_get_powermode\n"); */
+ /* wrqu->power.disabled = 0; */
+ /* wrqu->power.value = 1; */
+
+ struct iw_param *prPower = (struct iw_param *)&wrqu->power;
+ PARAM_POWER_MODE ePowerMode;
+
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4BufLen = 0;
+
+ ASSERT(prNetDev);
+ ASSERT(prPower);
+ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
+ return -EINVAL;
+ }
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+ ASSERT(prGlueInfo);
+
+
+#if 1
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidQueryP2pPowerSaveProfile,
+ &ePowerMode, sizeof(ePowerMode), TRUE, FALSE, FALSE, TRUE, &u4BufLen);
+#else
+ rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
+ wlanoidQueryP2pPowerSaveProfile,
+ &ePowerMode, sizeof(ePowerMode), &u4BufLen);
+#endif
+
+ prPower->value = 0;
+ prPower->disabled = 1;
+
+ if (Param_PowerModeCAM == ePowerMode) {
+ prPower->value = 0;
+ prPower->disabled = 1;
+ } else if (Param_PowerModeMAX_PSP == ePowerMode) {
+ prPower->value = 1;
+ prPower->disabled = 0;
+ } else if (Param_PowerModeFast_PSP == ePowerMode) {
+ prPower->value = 2;
+ prPower->disabled = 0;
+ }
+
+ prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE;
+#if WIRELESS_EXT < 21
+ prPower->value *= 1000000;
+#endif
+
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_CFG_DEVICE)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_CFG_DEVICE_TYPE prDeviceCfg = (P_IW_P2P_CFG_DEVICE_TYPE) extra;
+ P_P2P_CONNECTION_SETTINGS_T prConnSettings;
+ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL;
+ /* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; */
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings;
+ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo;
+
+ /* update connection settings for P2P-FSM */
+ /* 1. update SSID */
+ if (prDeviceCfg->ssid_len > ELEM_MAX_LEN_SSID) {
+ prConnSettings->ucSSIDLen = ELEM_MAX_LEN_SSID;
+ } else {
+ prConnSettings->ucSSIDLen = prDeviceCfg->ssid_len;
+ }
+
+ if (copy_from_user(prConnSettings->aucSSID, prDeviceCfg->ssid, prConnSettings->ucSSIDLen)) {
+ return -EFAULT;
+ }
+ /* 2. update device type (WPS IE) */
+ kalMemCopy(&(prConnSettings->rPrimaryDevTypeBE), &(prDeviceCfg->pri_device_type),
+ sizeof(DEVICE_TYPE_T));
+#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT
+ kalMemCopy(&(prConnSettings->arSecondaryDevTypeBE[0]), &(prDeviceCfg->snd_device_type),
+ sizeof(DEVICE_TYPE_T));
+#endif
+
+ /* 3. update device name */
+ if (prDeviceCfg->device_name_len > WPS_ATTRI_MAX_LEN_DEVICE_NAME) {
+ prConnSettings->ucDevNameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME;
+ } else {
+ prConnSettings->ucDevNameLen = prDeviceCfg->device_name_len;
+ }
+ if (copy_from_user
+ (prConnSettings->aucDevName, prDeviceCfg->device_name, prConnSettings->ucDevNameLen)) {
+ return -EFAULT;
+ }
+ /* 4. update GO intent */
+ prConnSettings->ucGoIntent = prDeviceCfg->intend;
+
+
+ /* Preferred channel bandwidth */
+ prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode =
+ prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M;
+ prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode =
+ prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M;
+
+#if 0
+ /* 1. switch P2P-FSM on */
+ /* 1.1 allocate for message */
+ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof(MSG_P2P_FUNCTION_SWITCH_T));
+
+ if (!prFuncSwitch) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ /* 1.2 fill message */
+ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH;
+ prFuncSwitch->fgIsFuncOn = TRUE;
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF);
+#endif
+ return 0;
+} /* end of mtk_p2p_wext_set_local_dev_info() */
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief I/O Control handler for both
+ * IOC_P2P_START_STOP_DISCOVERY & SIOCGIWSCAN
+ *
+ * \param[in] prDev Net device requested.
+ * \param[inout] wrqu Pointer to iwreq_data
+ *
+ * \retval 0 Success.
+ * \retval -EFAULT Setting parameters to driver fail.
+ * \retval -EOPNOTSUPP Key size not supported.
+ *
+ * \note
+ */
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_discovery_results(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ struct iw_event iwe;
+ char *current_ev = extra;
+ UINT_32 i;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_ADAPTER_T prAdapter = NULL;
+ P_P2P_INFO_T prP2PInfo = (P_P2P_INFO_T) NULL;
+ P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL;
+ P_PARAM_VARIABLE_IE_T prDesiredIE = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prP2PInfo = prAdapter->prP2pInfo;
+
+ for (i = 0; i < prP2PInfo->u4DeviceNum; i++) {
+ prTargetResult = &prP2PInfo->arP2pDiscoverResult[i];
+
+ /* SIOCGIWAP */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, prTargetResult->aucInterfaceAddr, 6);
+
+ current_ev = iwe_stream_add_event(info, current_ev,
+ extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN);
+
+
+ /* SIOCGIWESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = prTargetResult->u2NameLength;
+
+ current_ev = iwe_stream_add_point(info, current_ev,
+ extra + IW_SCAN_MAX_DATA,
+ &iwe, prTargetResult->aucName);
+
+ /* IWEVGENIE for WPA IE */
+ if (prTargetResult->u2IELength <= 600
+ && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, prTargetResult->u2IELength,
+ 0xDD, (PUINT_8 *) &prDesiredIE)) {
+
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+
+ current_ev = iwe_stream_add_point(info, current_ev,
+ extra + IW_SCAN_MAX_DATA,
+ &iwe, (char *)prDesiredIE);
+ }
+#if CFG_SUPPORT_WPS
+
+ /* IWEVGENIE for WPS IE */
+ if ((prTargetResult->u2IELength <= 600)
+ && wextSrchDesiredWPSIE(prTargetResult->pucIeBuf, prTargetResult->u2IELength,
+ 0xDD, (PUINT_8 *) &prDesiredIE)) {
+
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+
+ current_ev = iwe_stream_add_point(info, current_ev,
+ extra + IW_SCAN_MAX_DATA,
+ &iwe, (char *)prDesiredIE);
+ }
+#endif
+
+ /* IWEVGENIE for RSN IE */
+ if ((prTargetResult->u2IELength <= 600)
+ && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, prTargetResult->u2IELength,
+ 0x30, (PUINT_8 *) &prDesiredIE)) {
+
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+
+ current_ev = iwe_stream_add_point(info, current_ev,
+ extra + IW_SCAN_MAX_DATA,
+ &iwe, (char *)prDesiredIE);
+ }
+
+ /* IOC_P2P_GO_WSC_IE */
+#if 1
+ /* device capability */
+ if (1) {
+ UINT_8 data[40];
+
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.flags = 0;
+ iwe.u.data.length = 8 + sizeof("p2p_cap=");
+
+ snprintf(data, iwe.u.data.length, "p2p_cap=%02x%02x%02x%02x%c",
+ prTargetResult->ucDeviceCapabilityBitmap,
+ prTargetResult->ucGroupCapabilityBitmap,
+ (UINT_8) prTargetResult->u2ConfigMethod,
+ (UINT_8) (prTargetResult->u2ConfigMethod >> 8), '\0');
+ current_ev =
+ iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe,
+ (char *)data);
+
+ /* printk("%s\n", data); */
+ kalMemZero(data, 40);
+
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.flags = 0;
+ iwe.u.data.length = 12 + sizeof("p2p_dev_type=");
+
+ snprintf(data, iwe.u.data.length, "p2p_dev_type=%02x%02x%02x%02x%02x%02x%c",
+ (UINT_8) prTargetResult->rPriDevType.u2CategoryID,
+ (UINT_8) prTargetResult->rPriDevType.u2SubCategoryID,
+ (UINT_8) prTargetResult->arSecDevType[0].u2CategoryID,
+ (UINT_8) prTargetResult->arSecDevType[0].u2SubCategoryID,
+ (UINT_8) prTargetResult->arSecDevType[1].u2CategoryID,
+ (UINT_8) prTargetResult->arSecDevType[1].u2SubCategoryID, '\0');
+ current_ev =
+ iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe,
+ (char *)data);
+ /* printk("%s\n", data); */
+
+ kalMemZero(data, 40);
+
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.flags = 0;
+ iwe.u.data.length = 17 + sizeof("p2p_grp_bssid=");
+
+ snprintf(data, iwe.u.data.length, "p2p_grp_bssid=" MACSTR "%c",
+ MAC2STR(prTargetResult->aucBSSID), '\0');
+ current_ev = iwe_stream_add_point(info, current_ev,
+ extra + IW_SCAN_MAX_DATA,
+ &iwe, (char *)data);
+ /* printk("%s\n", data); */
+
+ }
+#endif
+ }
+
+ /* Length of data */
+ wrqu->data.length = (current_ev - extra);
+ wrqu->data.flags = 0;
+
+ return 0;
+} /* end of mtk_p2p_wext_discovery_results() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_WSC_BEACON_PROBE_RSP_IE)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_wsc_ie(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_HOSTAPD_PARAM prHostapdParam = (P_IW_P2P_HOSTAPD_PARAM) extra;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ if (prHostapdParam->len > 0) {
+ if (prHostapdParam->len <= MAX_WSC_IE_LENGTH) {
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[0], prHostapdParam->data,
+ prHostapdParam->len)) {
+ return -EFAULT;
+ }
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[2], prHostapdParam->data,
+ prHostapdParam->len)) {
+ return -EFAULT;
+ }
+ } else {
+ return -E2BIG;
+ }
+ }
+
+ prGlueInfo->prP2PInfo->u2WSCIELen[0] = prHostapdParam->len;
+ prGlueInfo->prP2PInfo->u2WSCIELen[2] = prHostapdParam->len;
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX);
+
+ /* @TODO: send message to P2P-FSM */
+
+ return 0;
+} /* end of mtk_p2p_wext_wsc_ie() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_CONNECT_DISCONNECT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+/* P_IW_P2P_CONNECT_DEVICE prConnectDevice = (P_IW_P2P_CONNECT_DEVICE)extra; */
+/* P_MSG_HDR_T prMsgHdr; */
+/* P_MSG_P2P_CONNECTION_REQUEST_T prMsgP2PConnReq; */
+/* P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt; */
+/* UINT_8 aucBCAddr[] = BC_MAC_ADDR; */
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ if (prData->flags == P2P_CONNECT) {
+#if 0
+ /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_REQ */
+ prMsgP2PConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof
+ (MSG_P2P_CONNECTION_REQUEST_T));
+
+ if (!prMsgP2PConnReq) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnReq, MSG_SEND_METHOD_BUF);
+#endif
+ } else if (prData->flags == P2P_DISCONNECT) {
+#if 0
+ /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_ABORT */
+ prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG,
+ sizeof(MSG_P2P_CONNECTION_ABORT_T));
+
+ if (!prMsgP2PConnAbt) {
+ ASSERT(0); /* Can't trigger P2P FSM */
+ return -ENOMEM;
+ }
+
+ COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prConnectDevice->sta_addr);
+
+ prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT;
+
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF);
+#endif
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+} /* end of mtk_p2p_wext_connect_disconnect() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_PASSWORD_READY)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_password_ready(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_PASSWORD_READY prPasswordReady = (P_IW_P2P_PASSWORD_READY) extra;
+ P_P2P_CONNECTION_SETTINGS_T prConnSettings;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings;
+
+ /* retrieve IE for Probe Request */
+ if (prPasswordReady->probe_req_len > 0) {
+ if (prPasswordReady->probe_req_len <= MAX_WSC_IE_LENGTH) {
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[1], prPasswordReady->probe_req_ie,
+ prPasswordReady->probe_req_len)) {
+ return -EFAULT;
+ }
+ } else {
+ return -E2BIG;
+ }
+ }
+
+ prGlueInfo->prP2PInfo->u2WSCIELen[1] = prPasswordReady->probe_req_len;
+
+ /* retrieve IE for Probe Response */
+ if (prPasswordReady->probe_rsp_len > 0) {
+ if (prPasswordReady->probe_rsp_len <= MAX_WSC_IE_LENGTH) {
+ if (copy_from_user
+ (prGlueInfo->prP2PInfo->aucWSCIE[2], prPasswordReady->probe_rsp_ie,
+ prPasswordReady->probe_rsp_len)) {
+ return -EFAULT;
+ }
+ } else {
+ return -E2BIG;
+ }
+ }
+
+ prGlueInfo->prP2PInfo->u2WSCIELen[2] = prPasswordReady->probe_rsp_len;
+
+ switch (prPasswordReady->active_config_method) {
+ case 1:
+ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_PUSH_BUTTON;
+ break;
+ case 2:
+ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_KEYPAD;
+ break;
+ case 3:
+ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_DISPLAY;
+ break;
+ default:
+ break;
+ }
+
+ prConnSettings->fgIsPasswordIDRdy = TRUE;
+ return 0;
+} /* end of mtk_p2p_wext_password_ready() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_GET_REQ_DEVICE_INFO)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_request_dev_info(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_DEVICE_REQ prDeviceReq = (P_IW_P2P_DEVICE_REQ) extra;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* specify data length */
+ wrqu->data.length = sizeof(IW_P2P_DEVICE_REQ);
+
+ /* copy to upper-layer supplied buffer */
+ kalMemCopy(prDeviceReq->name, prGlueInfo->prP2PInfo->aucConnReqDevName,
+ prGlueInfo->prP2PInfo->u4ConnReqNameLength);
+ prDeviceReq->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength;
+ prDeviceReq->name[prDeviceReq->name_len] = '\0';
+ COPY_MAC_ADDR(prDeviceReq->device_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr);
+ prDeviceReq->device_type = prGlueInfo->prP2PInfo->ucConnReqDevType;
+ prDeviceReq->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod;
+ prDeviceReq->active_config_method = prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod;
+
+ return 0;
+} /* end of mtk_p2p_wext_request_dev_info() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_IOCTL_INVITATION_INDICATE prInvIndicate =
+ (P_IW_P2P_IOCTL_INVITATION_INDICATE) extra;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* specify data length */
+ wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_INDICATE);
+
+ /* copy to upper-layer supplied buffer */
+ kalMemCopy(prInvIndicate->dev_name, prGlueInfo->prP2PInfo->aucConnReqDevName,
+ prGlueInfo->prP2PInfo->u4ConnReqNameLength);
+ kalMemCopy(prInvIndicate->group_bssid, prGlueInfo->prP2PInfo->rConnReqGroupAddr,
+ MAC_ADDR_LEN);
+ prInvIndicate->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength;
+ prInvIndicate->dev_name[prInvIndicate->name_len] = '\0';
+ COPY_MAC_ADDR(prInvIndicate->dev_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr);
+ prInvIndicate->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod;
+ prInvIndicate->operating_channel = prGlueInfo->prP2PInfo->ucOperatingChnl;
+ prInvIndicate->invitation_type = prGlueInfo->prP2PInfo->ucInvitationType;
+
+ return 0;
+} /* end of mtk_p2p_wext_invitation_indicate() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_invitation_status(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_IOCTL_INVITATION_STATUS prInvStatus = (P_IW_P2P_IOCTL_INVITATION_STATUS) extra;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* specify data length */
+ wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_STATUS);
+
+ /* copy to upper-layer supplied buffer */
+ prInvStatus->status_code = prGlueInfo->prP2PInfo->u4InvStatus;
+
+ return 0;
+} /* end of mtk_p2p_wext_invitation_status() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief indicate an event to supplicant for device found
+*
+* \param[in] prGlueInfo Pointer of GLUE_INFO_T
+*
+* \retval TRUE Success.
+* \retval FALSE Failure
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo)
+{
+ union iwreq_data evt;
+ UINT_8 aucBuffer[IW_CUSTOM_MAX];
+
+ ASSERT(prGlueInfo);
+
+ memset(&evt, 0, sizeof(evt));
+
+ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_FND");
+ evt.data.length = strlen(aucBuffer);
+
+ /* indicate IWEVP2PDVCFND event */
+ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer);
+
+ return FALSE;
+} /* end of kalP2PIndicateFound() */
+
+int
+mtk_p2p_wext_set_network_address(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* @TODO: invoke wlan_p2p functions */
+#if 0
+ rStatus = kalIoctl(prGlueInfo,
+ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pNetworkAddress,
+ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen);
+#endif
+
+ return 0;
+
+}
+
+int
+mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* @TODO: invoke wlan_p2p functions */
+#if 0
+ rStatus = kalIoctl(prGlueInfo,
+ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile,
+ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen);
+#endif
+
+ return 0;
+
+}
+
+int
+mtk_p2p_wext_set_pm_param(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ P_ADAPTER_T prAdapter = NULL;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prAdapter = prGlueInfo->prAdapter;
+ ASSERT(prAdapter);
+
+ /* @TODO: invoke wlan_p2p functions */
+#if 0
+ rStatus = kalIoctl(prGlueInfo,
+ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile,
+ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen);
+#endif
+
+ return 0;
+
+}
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Setting parameters not support.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_start_formation(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int i4Status = 0;
+ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL;
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+/* struct iw_point *prData = (struct iw_point*)&wrqu->data; */
+ P_IW_P2P_IOCTL_START_FORMATION prIoctlStartFormation =
+ (P_IW_P2P_IOCTL_START_FORMATION) NULL;
+
+ do {
+ if ((prDev == NULL) || (extra == NULL)) {
+ ASSERT(FALSE);
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION) extra;
+
+ if (prGlueInfo == NULL) {
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ prAdapter = prGlueInfo->prAdapter;
+
+ if (prAdapter == NULL) {
+ i4Status = -EINVAL;
+ break;
+ }
+
+
+ } while (FALSE);
+
+ return i4Status;
+
+}
+
+/* mtk_p2p_wext_start_formation */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Setting parameters not support.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_int(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int status = 0;
+ UINT_32 u4SubCmd = 0;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ UINT_32 index;
+ INT_32 value;
+ PUINT_32 pu4IntBuf;
+ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL;
+ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL;
+ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL;
+ UINT_32 u4Leng;
+
+ ASSERT(prDev);
+ ASSERT(wrqu);
+
+ /* printk("mtk_p2p_wext_set_int\n"); */
+ pu4IntBuf = (PUINT_32) extra;
+
+ if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) {
+ return -EINVAL;
+ }
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo;
+ prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings;
+ prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo;
+
+ u4SubCmd = (UINT_32) wrqu->mode;
+ index = pu4IntBuf[1];
+ value = pu4IntBuf[2];
+
+ printk("set parameter, u4SubCmd=%d idx=%d value=%lu\n", (INT_16) u4SubCmd, (INT_16) index,
+ value);
+
+ switch (u4SubCmd) {
+ case PRIV_CMD_INT_P2P_SET:
+ switch (index) {
+ case 0: /* Listen CH */
+ {
+ UINT_8 ucSuggestChnl = 0;
+
+ prP2pConnSettings->ucListenChnl = value;
+
+ /* 20110920 - frog: User configurations are placed in ConnSettings. */
+ if (rlmFuncFindAvailableChannel
+ (prGlueInfo->prAdapter, value, &ucSuggestChnl, TRUE, TRUE)) {
+ prP2pSpecificBssInfo->ucListenChannel = value;
+ } else {
+ prP2pSpecificBssInfo->ucListenChannel = ucSuggestChnl;
+ }
+
+
+ break;
+ }
+ case 1: /* P2p mode */
+ break;
+ case 4: /* Noa duration */
+ prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value;
+ /* only to apply setting when setting NOA count */
+ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */
+ break;
+ case 5: /* Noa interval */
+ prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value;
+ /* only to apply setting when setting NOA count */
+ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */
+ break;
+ case 6: /* Noa count */
+ prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value;
+ status =
+ mtk_p2p_wext_set_noa_param(prDev, info, wrqu,
+ (char *)&prP2pSpecificBssInfo->rNoaParam);
+ break;
+ case 100: /* Oper CH */
+ /* 20110920 - frog: User configurations are placed in ConnSettings. */
+ prP2pConnSettings->ucOperatingChnl = value;
+ break;
+ case 101: /* Local config Method, for P2P SDK */
+ /* prP2pConnSettings->u2LocalConfigMethod; */
+ break;
+ case 102: /* Sigma P2p reset */
+ kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN);
+ /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */
+ break;
+ case 103: /* WPS MODE */
+ kalP2PSetWscMode(prGlueInfo, value);
+ break;
+ case 104: /* P2p send persence, duration */
+ break;
+ case 105: /* P2p send persence, interval */
+ break;
+ case 106: /* P2P set sleep */
+ value = 1;
+ kalIoctl(prGlueInfo,
+ wlanoidSetP2pPowerSaveProfile,
+ &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng);
+ break;
+ case 107: /* P2P set opps, CTWindowl */
+ prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value;
+ status =
+ mtk_p2p_wext_set_oppps_param(prDev, info, wrqu,
+ (char *)&prP2pSpecificBssInfo->
+ rOppPsParam);
+ break;
+ case 108: /* p2p_set_power_save */
+ kalIoctl(prGlueInfo,
+ wlanoidSetP2pPowerSaveProfile,
+ &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng);
+
+ break;
+
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_SET_STRUCT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_struct(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int status = 0;
+ UINT_32 u4SubCmd = 0;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL;
+
+ ASSERT(prDev);
+ ASSERT(wrqu);
+
+ if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) {
+ return -EINVAL;
+ }
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ u4SubCmd = (UINT_32) wrqu->data.flags;
+
+ kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], sizeof(prGlueInfo->prP2PInfo->aucOidBuf));
+
+ switch (u4SubCmd) {
+ case PRIV_CMD_OID:
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.pointer, wrqu->data.length)) {
+ status = -EFAULT;
+ break;
+ }
+
+ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) {
+ printk(KERN_INFO DRV_NAME "extra buffer is valid\n");
+ } else {
+ printk(KERN_INFO DRV_NAME "extra 0x%p\n", extra);
+ }
+
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0]));
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_SEND_SD_RESPONSE:
+ status =
+ mtk_p2p_wext_send_service_discovery_response(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+
+ case P2P_CMD_ID_SEND_SD_REQUEST:
+ status =
+ mtk_p2p_wext_send_service_discovery_request(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+
+ case P2P_CMD_ID_TERMINATE_SD_PHASE:
+ status =
+ mtk_p2p_wext_terminate_service_discovery_phase(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+
+ case P2P_CMD_ID_INVITATION:
+ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_INVITATION_STRUCT)) {
+/* status = mtk_p2p_wext_invitation_request(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); */
+ }
+ break;
+
+ case P2P_CMD_ID_INVITATION_ABORT:
+ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_ABORT_INVITATION)) {
+/* status = mtk_p2p_wext_invitation_abort(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); */
+ }
+ break;
+
+ case P2P_CMD_ID_START_FORMATION:
+ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_START_FORMATION)) {
+ status =
+ mtk_p2p_wext_start_formation(prDev, info, wrqu,
+ (char *)(prP2PReq->aucBuffer));
+ }
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ }
+
+ break;
+#if CFG_SUPPORT_ANTI_PIRACY
+ case PRIV_SEC_CHECK_OID:
+ if (wrqu->data.length > 256) {
+ status = -EOPNOTSUPP;
+ break;
+ }
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]),
+ wrqu->data.pointer, wrqu->data.length)) {
+ status = -EFAULT;
+ break;
+ }
+
+ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), extra, wrqu->data.length)) {
+ printk(KERN_INFO DRV_NAME "extra buffer is valid\n");
+ } else {
+ printk(KERN_INFO DRV_NAME "extra 0x%p\n", extra);
+ }
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0]));
+
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_SEC_CHECK:
+ status =
+ mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq);
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ }
+ break;
+#endif
+ case PRIV_CMD_P2P_VERSION:
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.pointer, wrqu->data.length)) {
+ status = -EFAULT;
+ break;
+ }
+
+ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) {
+ printk(KERN_INFO DRV_NAME "extra buffer is valid\n");
+ } else {
+ printk(KERN_INFO DRV_NAME "extra 0x%p\n", extra);
+ }
+
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0]));
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_P2P_VERSION:
+ status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq);
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ break;
+ }
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ break;
+ }
+
+ return status;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT)
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_struct(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ int status = 0;
+ UINT_32 u4SubCmd = 0;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL;
+
+ ASSERT(prDev);
+ ASSERT(wrqu);
+
+ if (!prDev || !wrqu) {
+ printk(KERN_INFO DRV_NAME "%s(): invalid param(0x%p, 0x%p)\n",
+ __func__, prDev, wrqu);
+ return -EINVAL;
+ }
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ u4SubCmd = (UINT_32) wrqu->data.flags;
+
+ kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ sizeof(prGlueInfo->prP2PInfo->aucOidBuf));
+
+ switch (u4SubCmd) {
+ case PRIV_CMD_OID:
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) {
+ printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__);
+ return -EFAULT;
+ }
+
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0]));
+
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_GET_SD_REQUEST:
+ status =
+ mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+
+ case P2P_CMD_ID_GET_SD_RESPONSE:
+ status =
+ mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+
+ case P2P_CMD_ID_INVITATION_INDICATE:
+ {
+ status =
+ mtk_p2p_wext_invitation_indicate(prDev, info, wrqu,
+ (char *)(prP2PReq->aucBuffer));
+ prP2PReq->outBufferLength = wrqu->data.length;
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.length +
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ break;
+ }
+ case P2P_CMD_ID_INVITATION_STATUS:
+ {
+ status =
+ mtk_p2p_wext_invitation_status(prDev, info, wrqu,
+ (char *)(prP2PReq->aucBuffer));
+ prP2PReq->outBufferLength = wrqu->data.length;
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.length +
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ break;
+ }
+ case P2P_CMD_ID_GET_CH_LIST:
+ {
+ UINT_16 i;
+ UINT_8 NumOfChannel = 50;
+ RF_CHANNEL_INFO_T aucChannelList[50];
+ UINT_8 ucMaxChannelNum = 50;
+ PUINT_8 pucChnlList = (PUINT_8) prP2PReq->aucBuffer;
+
+ kalGetChnlList(prGlueInfo, BAND_NULL, ucMaxChannelNum,
+ &NumOfChannel, aucChannelList);
+ if (NumOfChannel > 50)
+ NumOfChannel = 50;
+ prP2PReq->outBufferLength = NumOfChannel;
+
+ for (i = 0; i < NumOfChannel; i++) {
+#if 0
+ /* 20120208 frog: modify to avoid clockwork warning. */
+ prP2PReq->aucBuffer[i] = aucChannelList[i].ucChannelNum;
+#else
+ *pucChnlList = aucChannelList[i].ucChannelNum;
+ pucChnlList++;
+#endif
+ }
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ NumOfChannel + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT,
+ aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ break;
+ }
+
+ case P2P_CMD_ID_GET_OP_CH:
+ {
+ prP2PReq->inBufferLength = 4;
+
+ status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength,
+ &prP2PReq->outBufferLength);
+
+ if (status == 0) { /* WLAN_STATUS_SUCCESS */
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ prP2PReq->outBufferLength +
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT,
+ aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n",
+ __func__);
+ return -EIO;
+ }
+ } else {
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT,
+ aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n",
+ __func__);
+ return -EIO;
+ }
+ }
+ break;
+ }
+
+ default:
+ status = -EOPNOTSUPP;
+ }
+
+ break;
+#if CFG_SUPPORT_ANTI_PIRACY
+ case PRIV_SEC_CHECK_OID:
+ if (wrqu->data.length > 256) {
+ status = -EOPNOTSUPP;
+ break;
+ }
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]),
+ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) {
+ printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__);
+ return -EFAULT;
+ }
+
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0]));
+
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_SEC_CHECK:
+ status =
+ mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu,
+ (char *)prP2PReq);
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ }
+ break;
+#endif
+ case PRIV_CMD_P2P_VERSION:
+ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) {
+ printk(KERN_NOTICE "%s() copy_from_user oidBuf fail\n", __func__);
+ return -EFAULT;
+ }
+
+ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0]));
+
+ switch (prP2PReq->u4CmdId) {
+ case P2P_CMD_ID_P2P_VERSION:
+ status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq);
+ break;
+ default:
+ status = -EOPNOTSUPP;
+ break;
+ }
+
+
+ /* Copy queried data to user. */
+ if (status == 0) { /* WLAN_STATUS_SUCCESS */
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ prP2PReq->outBufferLength +
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ }
+ }
+
+ else {
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ }
+ }
+
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return status;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+* getting service discovery request frame from driver
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4QueryInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidGetP2PSDRequest,
+ prP2PReq->aucBuffer,
+ prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ prP2PReq->outBufferLength = u4QueryInfoLen;
+
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+* getting service discovery response frame from driver
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4QueryInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidGetP2PSDResponse,
+ prP2PReq->aucBuffer,
+ prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ prP2PReq->outBufferLength = u4QueryInfoLen;
+
+ if (copy_to_user(wrqu->data.pointer,
+ &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+ u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+* sending service discovery request frame
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSendP2PSDRequest,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+* sending service discovery response frame
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSendP2PSDResponse,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+#if CFG_SUPPORT_ANTI_PIRACY
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetSecCheckRequest,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4QueryInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ printk("mtk_p2p_wext_get_sec_check_response\n");
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidGetSecCheckResponse,
+ prP2PReq->aucBuffer,
+ prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ prP2PReq->outBufferLength = u4QueryInfoLen;
+
+ if (copy_to_user(wrqu->data.pointer,
+ prP2PReq->aucBuffer,
+ u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+ printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+* terminating service discovery phase
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetP2PTerminateSDPhase,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_noa_param(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+ /* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */
+ P_PARAM_CUSTOM_NOA_PARAM_STRUC_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ printk("mtk_p2p_wext_set_noa_param\n");
+
+ rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, prNoaParam, /* prP2PReq->aucBuffer, */
+ sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T), /* prP2PReq->inBufferLength, */
+ FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief P2P Private I/O Control handler for
+*
+* \param[in] prDev Net device requested.
+* \param[inout] wrqu Pointer to iwreq_data
+*
+* \retval 0 Success.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int
+mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4SetInfoLen;
+/* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */
+ P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T prOppPsParam =
+ (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ printk("mtk_p2p_wext_set_oppps_param\n");
+
+ rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, prOppPsParam, /* prP2PReq->aucBuffer, */
+ sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T), /* prP2PReq->inBufferLength, */
+ FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+
+int
+mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ UINT_32 u4SetInfoLen;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidSetP2pSupplicantVersion,
+ prP2PReq->aucBuffer,
+ prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return rStatus;
+ }
+
+
+}
+
+/* mtk_p2p_wext_set_p2p_version */
+
+int
+mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4QueryInfoLen;
+ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidQueryP2pVersion,
+ prP2PReq->aucBuffer,
+ prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen);
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return rStatus;
+ }
+
+
+} /* mtk_p2p_wext_get_p2p_version */
+
+#if CFG_SUPPORT_P2P_RSSI_QUERY
+
+int
+mtk_p2p_wext_get_rssi(IN struct net_device *prDev,
+ IN struct iw_request_info *info,
+ IN OUT union iwreq_data *wrqu, IN OUT char *extra)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+ UINT_32 u4QueryInfoLen;
+ struct iw_point *prData = (struct iw_point *)&wrqu->data;
+ UINT_16 u2BufferSize = 0;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ INT_32 i4Rssi;
+ struct iw_statistics *pStats = NULL;
+
+ ASSERT(prDev);
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+
+ if (!prGlueInfo) {
+ rStatus = WLAN_STATUS_FAILURE;
+ goto stat_out;
+ }
+
+ pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats));
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidQueryP2pRssi,
+ &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &u4QueryInfoLen);
+
+ u2BufferSize = prData->length;
+
+ if (u2BufferSize < sizeof(struct iw_statistics)) {
+ return -E2BIG;
+ }
+
+
+ if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) {
+ rStatus = WLAN_STATUS_FAILURE;
+ }
+
+
+ stat_out:
+
+ if (rStatus != WLAN_STATUS_SUCCESS) {
+ return -EFAULT;
+ } else {
+ return rStatus;
+ }
+
+} /* mtk_p2p_wext_get_rssi */
+
+struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev)
+{
+ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ struct iw_statistics *pStats = NULL;
+ INT_32 i4Rssi;
+ UINT_32 bufLen = 0;
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+ ASSERT(prGlueInfo);
+ if (!prGlueInfo) {
+ goto stat_out;
+ }
+
+ pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats));
+
+ if (!prDev || !netif_carrier_ok(prDev)) {
+ /* network not connected */
+ goto stat_out;
+ }
+
+ rStatus = kalIoctl(prGlueInfo,
+ wlanoidQueryP2pRssi,
+ &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &bufLen);
+
+ stat_out:
+ return pStats;
+} /* mtk_p2p_wext_get_wireless_stats */
+
+
+#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */
+
+
+int
+mtk_p2p_wext_set_txpow(IN struct net_device *prDev,
+ IN struct iw_request_info *prIwrInfo,
+ IN OUT union iwreq_data *prTxPow, IN char *pcExtra)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL;
+#if 0
+ P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL;
+#endif
+ int i4Ret = 0;
+
+ ASSERT(prDev);
+ ASSERT(prTxPow);
+
+ do {
+ if ((!prDev) || (!prTxPow)) {
+ i4Ret = -EINVAL;
+ break;
+ }
+
+
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+ if (!prGlueInfo) {
+ i4Ret = -EINVAL;
+ break;
+ }
+
+
+ prAdapter = prGlueInfo->prAdapter;
+#if 0
+ prMsgFuncSwitch =
+ (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof(MSG_P2P_FUNCTION_SWITCH_T));
+ if (!prMsgFuncSwitch) {
+ ASSERT(0);
+ return -ENOMEM;
+ }
+
+ prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH;
+
+ if (prTxPow->disabled) {
+ /* Dissolve. */
+ prMsgFuncSwitch->fgIsFuncOn = FALSE;
+ } else {
+
+ /* Re-enable function. */
+ prMsgFuncSwitch->fgIsFuncOn = TRUE;
+ }
+
+ /* 1.3 send message */
+ mboxSendMsg(prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF);
+#endif
+
+ } while (FALSE);
+
+ return i4Ret;
+} /* mtk_p2p_wext_set_txpow */