tdls.c 180 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251
  1. /******************************************************************************
  2. *
  3. * This file is provided under a dual license. When you use or
  4. * distribute this software, you may choose to be licensed under
  5. * version 2 of the GNU General Public License ("GPLv2 License")
  6. * or BSD License.
  7. *
  8. * GPLv2 License
  9. *
  10. * Copyright(C) 2016 MediaTek Inc.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of version 2 of the GNU General Public License as
  14. * published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19. * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
  20. *
  21. * BSD LICENSE
  22. *
  23. * Copyright(C) 2016 MediaTek Inc. All rights reserved.
  24. *
  25. * Redistribution and use in source and binary forms, with or without
  26. * modification, are permitted provided that the following conditions
  27. * are met:
  28. *
  29. * * Redistributions of source code must retain the above copyright
  30. * notice, this list of conditions and the following disclaimer.
  31. * * Redistributions in binary form must reproduce the above copyright
  32. * notice, this list of conditions and the following disclaimer in
  33. * the documentation and/or other materials provided with the
  34. * distribution.
  35. * * Neither the name of the copyright holder nor the names of its
  36. * contributors may be used to endorse or promote products derived
  37. * from this software without specific prior written permission.
  38. *
  39. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  40. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  41. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  42. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  43. * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  45. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  46. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  47. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  48. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  49. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  50. *
  51. *****************************************************************************/
  52. /*
  53. ** Id: tdls.c#1
  54. */
  55. /*! \file tdls.c
  56. \brief This file includes IEEE802.11z TDLS support.
  57. */
  58. /*
  59. ** Log: tdls.c
  60. *
  61. * 11 13 2013 vend_samp.lin
  62. * NULL
  63. * Initial version.
  64. */
  65. /*******************************************************************************
  66. * C O M P I L E R F L A G S
  67. ********************************************************************************
  68. */
  69. /*******************************************************************************
  70. * E X T E R N A L R E F E R E N C E S
  71. ********************************************************************************
  72. */
  73. #include "precomp.h"
  74. #if (CFG_SUPPORT_TDLS == 1)
  75. #include "gl_wext.h"
  76. #include "tdls.h"
  77. #include "gl_cfg80211.h"
  78. #include <uapi/linux/nl80211.h>
  79. /*******************************************************************************
  80. * C O N S T A N T S
  81. ********************************************************************************
  82. */
  83. /*******************************************************************************
  84. * F U N C T I O N D E C L A R A T I O N S
  85. ********************************************************************************
  86. */
  87. static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb);
  88. #if TDLS_CFG_CMD_TEST
  89. static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  90. static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  91. static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  92. static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  93. static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  94. static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  95. static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  96. static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  97. static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  98. static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  99. static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  100. static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  101. static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  102. static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  103. static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  104. static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  105. static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  106. static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  107. static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  108. static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  109. static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  110. static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  111. static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  112. static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  113. static TDLS_STATUS
  114. TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd);
  115. static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  116. static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  117. static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param);
  118. static TDLS_STATUS
  119. TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  120. static TDLS_STATUS
  121. TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  122. static TDLS_STATUS
  123. TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  124. static TDLS_STATUS
  125. TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  126. static TDLS_STATUS
  127. TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  128. static TDLS_STATUS
  129. TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  130. static TDLS_STATUS
  131. TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  132. static TDLS_STATUS
  133. TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  134. static TDLS_STATUS
  135. TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  136. static TDLS_STATUS
  137. TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  138. static TDLS_STATUS
  139. TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  140. static TDLS_STATUS
  141. TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  142. static TDLS_STATUS
  143. TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  144. static TDLS_STATUS
  145. TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  146. static TDLS_STATUS
  147. TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  148. static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  149. static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  150. static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  151. static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  152. static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  153. static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen);
  154. static TDLS_STATUS
  155. TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  156. static TDLS_STATUS
  157. TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  158. static VOID
  159. TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo,
  160. BOOLEAN fgIsTearDown,
  161. UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers);
  162. static VOID
  163. TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo,
  164. UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo);
  165. static TDLS_STATUS
  166. TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  167. static TDLS_STATUS
  168. TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  169. static TDLS_STATUS
  170. TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen);
  171. static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen);
  172. static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen);
  173. #endif /* TDLS_CFG_CMD_TEST */
  174. /*******************************************************************************
  175. * P R I V A T E D A T A
  176. ********************************************************************************
  177. */
  178. static BOOLEAN fgIsPtiTimeoutSkip = FALSE;
  179. /*******************************************************************************
  180. * P R I V A T E F U N C T I O N S
  181. ********************************************************************************
  182. */
  183. /*----------------------------------------------------------------------------*/
  184. /*!
  185. * \brief This routine is called to indicate packets to upper layer.
  186. *
  187. * \param[in] prGlueInfo Pointer to the Adapter structure
  188. * \param[in] prSkb A pointer to the received packet
  189. *
  190. * \retval None
  191. *
  192. */
  193. /*----------------------------------------------------------------------------*/
  194. static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb)
  195. {
  196. struct net_device *prNetDev;
  197. /* init */
  198. prNetDev = prGlueInfo->prDevHandler;
  199. prGlueInfo->rNetDevStats.rx_bytes += prSkb->len;
  200. prGlueInfo->rNetDevStats.rx_packets++;
  201. /* pass to upper layer */
  202. prNetDev->last_rx = jiffies;
  203. prSkb->protocol = eth_type_trans(prSkb, prNetDev);
  204. prSkb->dev = prNetDev;
  205. if (!in_interrupt())
  206. netif_rx_ni(prSkb); /* only in non-interrupt context */
  207. else
  208. netif_rx(prSkb);
  209. }
  210. #if TDLS_CFG_CMD_TEST
  211. #define LR_TDLS_FME_FIELD_FILL(__Len) \
  212. do { \
  213. pPkt += __Len; \
  214. u4PktLen += __Len; \
  215. } while (0)
  216. /*----------------------------------------------------------------------------*/
  217. /*! \brief This routine is called to add a TDLS peer.
  218. *
  219. * \param[in] prGlueInfo Pointer to the Adapter structure
  220. * \param[in] prInBuf A pointer to the command string buffer
  221. * \param[in] u4InBufLen The length of the buffer
  222. * \param[out] None
  223. *
  224. * \retval None
  225. *
  226. * EX: iwpriv wlan0 set_str_cmd 0_2_[Responder MAC]
  227. iwpriv wlan0 set_str_cmd 0_2_00:11:22:33:44:01
  228. */
  229. /*----------------------------------------------------------------------------*/
  230. static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  231. {
  232. PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd;
  233. struct wireless_dev *prWdev;
  234. /* reset */
  235. kalMemZero(&rCmd, sizeof(rCmd));
  236. /* parse arguments */
  237. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
  238. /* init */
  239. rCmd.rPeerInfo.supported_rates = NULL;
  240. rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa;
  241. rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */
  242. rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER);
  243. /* send command to wifi task to handle */
  244. prWdev = prGlueInfo->prDevHandler->ieee80211_ptr;
  245. mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo);
  246. }
  247. /*----------------------------------------------------------------------------*/
  248. /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
  249. *
  250. * \param[in] prGlueInfo Pointer to the Adapter structure
  251. * \param[in] prInBuf A pointer to the command string buffer
  252. * \param[in] u4InBufLen The length of the buffer
  253. * \param[out] None
  254. *
  255. * \retval None
  256. *
  257. * EX: iwpriv wlan0 set_str_cmd 0_16_[Enable/Disable]_[Set/Clear]
  258. iwpriv wlan0 set_str_cmd 0_16_1_1
  259. */
  260. /*----------------------------------------------------------------------------*/
  261. static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  262. {
  263. TDLS_CMD_CORE_T rCmd;
  264. /* parse arguments */
  265. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  266. rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  267. rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  268. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable);
  269. /* command to do this */
  270. flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable;
  271. aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP;
  272. aucTdlsTestExtCapElm[1] = 5;
  273. aucTdlsTestExtCapElm[2] = 0;
  274. aucTdlsTestExtCapElm[3] = 0;
  275. aucTdlsTestExtCapElm[4] = 0;
  276. aucTdlsTestExtCapElm[5] = 0;
  277. aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 7); /* bit39 */
  278. }
  279. /*----------------------------------------------------------------------------*/
  280. /*! \brief This routine is called to receive a channel switch request from the peer.
  281. *
  282. * \param[in] prGlueInfo Pointer to the Adapter structure
  283. * \param[in] prInBuf A pointer to the command string buffer
  284. * \param[in] u4InBufLen The length of the buffer
  285. * \param[out] None
  286. *
  287. * \retval None
  288. *
  289. * EX: iwpriv wlan0 set_str_cmd 0_1_5_[TDLS Peer MAC]_[Chan]_[RegulatoryClass]_
  290. [SecondaryChannelOffset]_[SwitchTime]_[SwitchTimeout]
  291. iwpriv wlan0 set_str_cmd 0_1_5_00:11:22:33:44:01_1_255_0_15000_30000
  292. RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
  293. Secondary Channel Offset: 0 (SCN - no secondary channel)
  294. 1 (SCA - secondary channel above)
  295. 2 (SCB - secondary channel below)
  296. SwitchTime: units of microseconds
  297. */
  298. /*----------------------------------------------------------------------------*/
  299. static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  300. {
  301. WLAN_STATUS rStatus;
  302. TDLS_CMD_CORE_T rCmd;
  303. UINT_32 u4BufLen;
  304. /* parse arguments */
  305. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  306. rCmd.Content.rCmdChStReqRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  307. rCmd.Content.rCmdChStReqRcv.u4RegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  308. rCmd.Content.rCmdChStReqRcv.u4SecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  309. rCmd.Content.rCmdChStReqRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  310. rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  311. DBGLOG(TDLS, INFO, "%s:[%pM]u4Chan=%u u4RegClass=%u u4SecChanOff=%u u4SwitchTime=%u u4SwitchTimeout=%u\n",
  312. __func__, rCmd.aucPeerMac,
  313. (UINT32) rCmd.Content.rCmdChStReqRcv.u4Chan,
  314. (UINT32) rCmd.Content.rCmdChStReqRcv.u4RegClass,
  315. (UINT32) rCmd.Content.rCmdChStReqRcv.u4SecChanOff,
  316. (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTime,
  317. (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout);
  318. /* command to do this */
  319. rStatus = kalIoctl(prGlueInfo, TdlsTestChStReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  320. if (rStatus != WLAN_STATUS_SUCCESS) {
  321. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  322. return;
  323. }
  324. }
  325. /*----------------------------------------------------------------------------*/
  326. /*! \brief This routine is called to receive a channel switch response from the peer.
  327. *
  328. * \param[in] prGlueInfo Pointer to the Adapter structure
  329. * \param[in] prInBuf A pointer to the command string buffer
  330. * \param[in] u4InBufLen The length of the buffer
  331. * \param[out] None
  332. *
  333. * \retval None
  334. *
  335. * EX: iwpriv wlan0 set_str_cmd 0_1_6_[TDLS Peer MAC]_[Chan]_
  336. [SwitchTime]_[SwitchTimeout]_[StatusCode]
  337. iwpriv wlan0 set_str_cmd 0_1_6_00:11:22:33:44:01_11_15000_30000_0
  338. RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
  339. Secondary Channel Offset: 0 (SCN - no secondary channel)
  340. 1 (SCA - secondary channel above)
  341. 2 (SCB - secondary channel below)
  342. SwitchTime: units of microseconds
  343. */
  344. /*----------------------------------------------------------------------------*/
  345. static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  346. {
  347. WLAN_STATUS rStatus;
  348. TDLS_CMD_CORE_T rCmd;
  349. UINT_32 u4BufLen;
  350. /* parse arguments */
  351. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  352. rCmd.Content.rCmdChStRspRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  353. rCmd.Content.rCmdChStRspRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  354. rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  355. rCmd.Content.rCmdChStRspRcv.u4StatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  356. DBGLOG(TDLS, INFO, "%s: [ %pM ] u4Chan=%u u4SwitchTime=%u u4SwitchTimeout=%u u4StatusCode=%u\n",
  357. __func__, rCmd.aucPeerMac,
  358. (UINT32) rCmd.Content.rCmdChStRspRcv.u4Chan,
  359. (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTime,
  360. (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout,
  361. (UINT32) rCmd.Content.rCmdChStRspRcv.u4StatusCode);
  362. /* command to do this */
  363. rStatus = kalIoctl(prGlueInfo, TdlsTestChStRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  364. if (rStatus != WLAN_STATUS_SUCCESS) {
  365. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  366. return;
  367. }
  368. }
  369. /*----------------------------------------------------------------------------*/
  370. /*! \brief This routine is called to inform firmware to skip channel switch timeout function.
  371. *
  372. * \param[in] prGlueInfo Pointer to the Adapter structure
  373. * \param[in] prInBuf A pointer to the command string buffer
  374. * \param[in] u4InBufLen The length of the buffer
  375. * \param[out] None
  376. *
  377. * \retval None
  378. *
  379. * EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]
  380. iwpriv wlan0 set_str_cmd 0_11_1
  381. */
  382. /*----------------------------------------------------------------------------*/
  383. static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  384. {
  385. WLAN_STATUS rStatus;
  386. TDLS_CMD_CORE_T rCmd;
  387. UINT_32 u4BufLen;
  388. /* parse arguments */
  389. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  390. rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  391. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable);
  392. /* command to do this */
  393. rStatus = kalIoctl(prGlueInfo,
  394. TdlsTestChSwTimeoutSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  395. if (rStatus != WLAN_STATUS_SUCCESS) {
  396. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  397. return;
  398. }
  399. }
  400. /*----------------------------------------------------------------------------*/
  401. /*! \brief This routine is called to send a data frame to the peer periodically.
  402. *
  403. * \param[in] prGlueInfo Pointer to the Adapter structure
  404. * \param[in] prInBuf A pointer to the command string buffer
  405. * \param[in] u4InBufLen The length of the buffer
  406. * \param[out] None
  407. *
  408. * \retval None
  409. *
  410. */
  411. /*----------------------------------------------------------------------------*/
  412. static TIMER_T rTdlsTimerTestDataSend;
  413. static UINT_8 aucTdlsTestDataSPeerMac[6];
  414. static UINT_16 u2TdlsTestDataSInterval;
  415. static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  416. {
  417. ADAPTER_T *prAdapter;
  418. BOOLEAN fgIsEnabled;
  419. /* init */
  420. prAdapter = prGlueInfo->prAdapter;
  421. /* parse arguments */
  422. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucTdlsTestDataSPeerMac);
  423. u2TdlsTestDataSInterval = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  424. fgIsEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  425. cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend);
  426. if (fgIsEnabled == FALSE) {
  427. /* stop test timer */
  428. return;
  429. }
  430. /* re-init test timer */
  431. cnmTimerInitTimer(prAdapter,
  432. &rTdlsTimerTestDataSend, (PFN_MGMT_TIMEOUT_FUNC) TdlsTimerTestDataContSend, (ULONG) NULL);
  433. cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval);
  434. }
  435. /*----------------------------------------------------------------------------*/
  436. /*! \brief This routine is called to receive a data frame from the peer.
  437. *
  438. * \param[in] prGlueInfo Pointer to the Adapter structure
  439. * \param[in] prInBuf A pointer to the command string buffer
  440. * \param[in] u4InBufLen The length of the buffer
  441. * \param[out] None
  442. *
  443. * \retval None
  444. *
  445. * EX: iwpriv wlan0 set_str_cmd 0_0_x80_[TDLS Peer MAC]_[PM]_[UP]_[EOSP]_[IsNull]
  446. iwpriv wlan0 set_str_cmd 0_1_x80_00:11:22:33:44:01_0_0_0_0
  447. */
  448. /*----------------------------------------------------------------------------*/
  449. static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  450. {
  451. WLAN_STATUS rStatus;
  452. TDLS_CMD_CORE_T rCmd;
  453. UINT_32 u4BufLen;
  454. /* parse arguments */
  455. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  456. rCmd.Content.rCmdDatRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  457. rCmd.Content.rCmdDatRcv.u4UP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  458. rCmd.Content.rCmdDatRcv.u4EOSP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  459. rCmd.Content.rCmdDatRcv.u4IsNull = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  460. DBGLOG(TDLS, INFO,
  461. "<tdls_cmd> %s: [%pM] PM(%u) UP(%u) EOSP(%u) NULL(%u)\n",
  462. __func__, rCmd.aucPeerMac,
  463. (UINT32) rCmd.Content.rCmdDatRcv.u4PM,
  464. (UINT32) rCmd.Content.rCmdDatRcv.u4UP,
  465. (UINT32) rCmd.Content.rCmdDatRcv.u4EOSP, (UINT32) rCmd.Content.rCmdDatRcv.u4IsNull);
  466. /* command to do this */
  467. rStatus = kalIoctl(prGlueInfo, TdlsTestDataRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  468. if (rStatus != WLAN_STATUS_SUCCESS) {
  469. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  470. return;
  471. }
  472. }
  473. /*----------------------------------------------------------------------------*/
  474. /*! \brief This routine is called to send a data frame to the peer.
  475. *
  476. * \param[in] prGlueInfo Pointer to the Adapter structure
  477. * \param[in] prInBuf A pointer to the command string buffer
  478. * \param[in] u4InBufLen The length of the buffer
  479. * \param[out] None
  480. *
  481. * \retval None
  482. *
  483. * EX: iwpriv wlan0 set_str_cmd 0_4_[Responder MAC]_[tx status]
  484. iwpriv wlan0 set_str_cmd 0_4_00:11:22:33:44:01_0
  485. */
  486. /*----------------------------------------------------------------------------*/
  487. static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  488. {
  489. P_ADAPTER_T prAdapter;
  490. struct sk_buff *prMsduInfo;
  491. UINT_8 *prPkt;
  492. UINT_8 MAC[6];
  493. UINT_8 ucTxStatus;
  494. /* init */
  495. prAdapter = prGlueInfo->prAdapter;
  496. /* parse arguments */
  497. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, MAC);
  498. ucTxStatus = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  499. /* allocate a data frame */
  500. prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt);
  501. if (prMsduInfo == NULL) {
  502. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s allocate pkt fail!\n", __func__);
  503. return;
  504. }
  505. /* init dev */
  506. prMsduInfo->dev = prGlueInfo->prDevHandler;
  507. if (prMsduInfo->dev == NULL) {
  508. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s prMsduInfo->dev == NULL!\n", __func__);
  509. kalPacketFree(prGlueInfo, prMsduInfo);
  510. return;
  511. }
  512. /* init packet */
  513. prMsduInfo->len = 1000;
  514. kalMemZero(prMsduInfo->data, 100); /* for QoS field */
  515. kalMemCopy(prMsduInfo->data, MAC, 6);
  516. kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6);
  517. *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800;
  518. /* simulate OS to send the packet */
  519. wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
  520. }
  521. /*----------------------------------------------------------------------------*/
  522. /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
  523. *
  524. * \param[in] prGlueInfo Pointer to the Adapter structure
  525. * \param[in] prInBuf A pointer to the command string buffer
  526. * \param[in] u4InBufLen The length of the buffer
  527. * \param[out] None
  528. *
  529. * \retval None
  530. *
  531. * EX: iwpriv wlan0 set_str_cmd 0_16_[mili seconds]
  532. iwpriv wlan0 set_str_cmd 0_19_1000
  533. */
  534. /*----------------------------------------------------------------------------*/
  535. static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  536. {
  537. UINT32 u4Delay;
  538. u4Delay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  539. DBGLOG(TDLS, INFO, "%s: Delay = %d\n", __func__, u4Delay);
  540. kalMdelay(u4Delay);
  541. }
  542. /*----------------------------------------------------------------------------*/
  543. /*! \brief This routine is called to receive a test discovery request frame command.
  544. *
  545. * \param[in] prGlueInfo Pointer to the Adapter structure
  546. * \param[in] prInBuf A pointer to the command string buffer
  547. * \param[in] u4InBufLen The length of the buffer
  548. * \param[out] None
  549. *
  550. * \retval None
  551. *
  552. * EX: iwpriv wlan0 set_str_cmd 0_1_10_[DialogToken]_[Peer MAC]_[BSSID]
  553. iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01
  554. iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01_00:22:33:44:11:22
  555. */
  556. /*----------------------------------------------------------------------------*/
  557. static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  558. {
  559. ADAPTER_T *prAdapter;
  560. P_BSS_INFO_T prBssInfo;
  561. struct sk_buff *prMsduInfo;
  562. UINT_8 *pPkt;
  563. UINT_32 u4PktLen, u4IeLen;
  564. UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6];
  565. /* parse arguments */
  566. ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  567. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
  568. kalMemZero(aucZeroMac, sizeof(aucZeroMac));
  569. kalMemZero(aucBSSID, sizeof(aucBSSID));
  570. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID);
  571. DBGLOG(TDLS, INFO,
  572. "<tdls_fme> %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac);
  573. /* allocate/init packet */
  574. prAdapter = prGlueInfo->prAdapter;
  575. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  576. u4PktLen = 0;
  577. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  578. if (prMsduInfo == NULL) {
  579. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  580. return;
  581. }
  582. prMsduInfo->dev = prGlueInfo->prDevHandler;
  583. if (prMsduInfo->dev == NULL) {
  584. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  585. kalPacketFree(prGlueInfo, prMsduInfo);
  586. return;
  587. }
  588. /* make up frame content */
  589. /* 1. 802.3 header */
  590. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  591. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  592. kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
  593. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  594. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  595. LR_TDLS_FME_FIELD_FILL(2);
  596. /* 2. payload type */
  597. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  598. LR_TDLS_FME_FIELD_FILL(1);
  599. /* 3. Frame Formation - (1) Category */
  600. *pPkt = TDLS_FRM_CATEGORY;
  601. LR_TDLS_FME_FIELD_FILL(1);
  602. /* 3. Frame Formation - (2) Action */
  603. *pPkt = TDLS_FRM_ACTION_DISCOVERY_REQ;
  604. LR_TDLS_FME_FIELD_FILL(1);
  605. /* 3. Frame Formation - (3) Dialog token */
  606. *pPkt = ucDialogToken;
  607. LR_TDLS_FME_FIELD_FILL(1);
  608. /* 3. Frame Formation - (16) Link identifier element */
  609. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  610. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18;
  611. if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0)
  612. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  613. else
  614. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6);
  615. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
  616. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
  617. u4IeLen = IE_SIZE(pPkt);
  618. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  619. /* 4. Update packet length */
  620. prMsduInfo->len = u4PktLen;
  621. dumpMemory8(prMsduInfo->data, u4PktLen);
  622. /* pass to OS */
  623. TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
  624. }
  625. /*----------------------------------------------------------------------------*/
  626. /*! \brief This routine is called to inform firmware to skip keep alive function.
  627. *
  628. * \param[in] prGlueInfo Pointer to the Adapter structure
  629. * \param[in] prInBuf A pointer to the command string buffer
  630. * \param[in] u4InBufLen The length of the buffer
  631. * \param[out] None
  632. *
  633. * \retval None
  634. *
  635. * EX: iwpriv wlan0 set_str_cmd 0_10_[Enable/Disable]
  636. iwpriv wlan0 set_str_cmd 0_10_1
  637. */
  638. /*----------------------------------------------------------------------------*/
  639. static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  640. {
  641. WLAN_STATUS rStatus;
  642. TDLS_CMD_CORE_T rCmd;
  643. UINT_32 u4BufLen;
  644. /* parse arguments */
  645. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  646. rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  647. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable);
  648. /* command to do this */
  649. rStatus = kalIoctl(prGlueInfo,
  650. TdlsTestKeepAliveSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  651. if (rStatus != WLAN_STATUS_SUCCESS) {
  652. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  653. return;
  654. }
  655. }
  656. /*----------------------------------------------------------------------------*/
  657. /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
  658. *
  659. * \param[in] prGlueInfo Pointer to the Adapter structure
  660. * \param[in] prInBuf A pointer to the command string buffer
  661. * \param[in] u4InBufLen The length of the buffer
  662. * \param[out] None
  663. *
  664. * \retval None
  665. *
  666. * EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]_[Set/Clear]
  667. iwpriv wlan0 set_str_cmd 0_13_1_1
  668. */
  669. /*----------------------------------------------------------------------------*/
  670. static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  671. {
  672. TDLS_CMD_CORE_T rCmd;
  673. /* parse arguments */
  674. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  675. rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  676. rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  677. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable);
  678. /* command to do this */
  679. flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable;
  680. aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP;
  681. aucTdlsTestExtCapElm[1] = 5;
  682. aucTdlsTestExtCapElm[2] = 0;
  683. aucTdlsTestExtCapElm[3] = 0;
  684. aucTdlsTestExtCapElm[4] = 0;
  685. aucTdlsTestExtCapElm[5] = 0;
  686. aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 6); /* bit38 */
  687. }
  688. /*----------------------------------------------------------------------------*/
  689. /*! \brief This routine is called to receive a PTI request from the AP.
  690. *
  691. * \param[in] prGlueInfo Pointer to the Adapter structure
  692. * \param[in] prInBuf A pointer to the command string buffer
  693. * \param[in] u4InBufLen The length of the buffer
  694. * \param[out] None
  695. *
  696. * \retval None
  697. *
  698. * EX: iwpriv wlan0 set_str_cmd 0_1_4_[TDLS Peer MAC]_[Dialog Token]
  699. iwpriv wlan0 set_str_cmd 0_1_4_00:11:22:33:44:01_0
  700. */
  701. /*----------------------------------------------------------------------------*/
  702. static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  703. {
  704. WLAN_STATUS rStatus;
  705. TDLS_CMD_CORE_T rCmd;
  706. UINT_32 u4BufLen;
  707. /* parse arguments */
  708. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  709. rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  710. DBGLOG(TDLS, INFO, "%s: [ %pM ] u4DialogToken = %u\n",
  711. __func__, rCmd.aucPeerMac, (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken);
  712. /* command to do this */
  713. rStatus = kalIoctl(prGlueInfo, TdlsTestPtiReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  714. if (rStatus != WLAN_STATUS_SUCCESS) {
  715. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  716. return;
  717. }
  718. }
  719. /*----------------------------------------------------------------------------*/
  720. /*! \brief This routine is called to receive a PTI response from the peer.
  721. *
  722. * \param[in] prGlueInfo Pointer to the Adapter structure
  723. * \param[in] prInBuf A pointer to the command string buffer
  724. * \param[in] u4InBufLen The length of the buffer
  725. * \param[out] None
  726. *
  727. * \retval None
  728. *
  729. * EX: iwpriv wlan0 set_str_cmd 0_1_9_[TDLS Peer MAC]_[Dialog Token]_[PM]
  730. iwpriv wlan0 set_str_cmd 0_1_9_00:11:22:33:44:01_0_1
  731. */
  732. /*----------------------------------------------------------------------------*/
  733. static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  734. {
  735. WLAN_STATUS rStatus;
  736. TDLS_CMD_CORE_T rCmd;
  737. UINT_32 u4BufLen;
  738. /* parse arguments */
  739. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  740. rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  741. rCmd.Content.rCmdPtiRspRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  742. DBGLOG(TDLS, INFO, "%s: [%pM] u4DialogToken = %u %u\n",
  743. __func__, rCmd.aucPeerMac,
  744. (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken,
  745. (UINT32) rCmd.Content.rCmdPtiRspRcv.u4PM);
  746. /* command to do this */
  747. rStatus = kalIoctl(prGlueInfo, TdlsTestPtiRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  748. if (rStatus != WLAN_STATUS_SUCCESS) {
  749. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  750. return;
  751. }
  752. }
  753. /*----------------------------------------------------------------------------*/
  754. /*! \brief This routine is called to inform firmware to simulate PTI tx done fail case.
  755. *
  756. * \param[in] prGlueInfo Pointer to the Adapter structure
  757. * \param[in] prInBuf A pointer to the command string buffer
  758. * \param[in] u4InBufLen The length of the buffer
  759. * \param[out] None
  760. *
  761. * \retval None
  762. *
  763. * EX: iwpriv wlan0 set_str_cmd 0_21_[Enable/Disable]
  764. iwpriv wlan0 set_str_cmd 0_21_1
  765. */
  766. /*----------------------------------------------------------------------------*/
  767. static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  768. {
  769. WLAN_STATUS rStatus;
  770. TDLS_CMD_CORE_T rCmd;
  771. UINT_32 u4BufLen;
  772. /* parse arguments */
  773. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  774. rCmd.Content.rCmdPtiTxFail.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  775. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdPtiTxFail.fgIsEnable);
  776. /* command to do this */
  777. rStatus = kalIoctl(prGlueInfo, TdlsTestPtiTxFail, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  778. if (rStatus != WLAN_STATUS_SUCCESS) {
  779. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  780. return;
  781. }
  782. }
  783. /*----------------------------------------------------------------------------*/
  784. /*! \brief This routine is called to receive a test frame.
  785. *
  786. * \param[in] prGlueInfo Pointer to the Adapter structure
  787. * \param[in] prInBuf A pointer to the command string buffer
  788. * \param[in] u4InBufLen The length of the buffer
  789. * \param[out] None
  790. *
  791. * \retval None
  792. *
  793. */
  794. /*----------------------------------------------------------------------------*/
  795. static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  796. {
  797. /* PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; */
  798. /* TDLS_STATUS u4Status; */
  799. UINT_32 u4Subcmd;
  800. /* UINT_32 u4BufLen; */
  801. /* parse sub-command */
  802. u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  803. DBGLOG(TDLS, INFO, "<tdls_cmd> test rv frame sub command = %u\n", (UINT32) u4Subcmd);
  804. /* parse command arguments */
  805. switch (u4Subcmd) {
  806. case TDLS_FRM_ACTION_SETUP_REQ:
  807. /* simulate to receive a setup request frame */
  808. TdlsCmdTestSetupReqRecv(prGlueInfo, prInBuf, u4InBufLen);
  809. break;
  810. case TDLS_FRM_ACTION_SETUP_RSP:
  811. /* simulate to receive a setup response frame */
  812. TdlsCmdTestSetupRspRecv(prGlueInfo, prInBuf, u4InBufLen);
  813. break;
  814. case TDLS_FRM_ACTION_CONFIRM:
  815. /* simulate to receive a setup confirm frame */
  816. TdlsCmdTestSetupConfirmRecv(prGlueInfo, prInBuf, u4InBufLen);
  817. break;
  818. case TDLS_FRM_ACTION_TEARDOWN:
  819. /* simulate to receive a tear down frame */
  820. TdlsCmdTestTearDownRecv(prGlueInfo, prInBuf, u4InBufLen);
  821. break;
  822. case TDLS_FRM_ACTION_PTI:
  823. /* simulate to receive a PTI request frame */
  824. TdlsCmdTestPtiReqRecv(prGlueInfo, prInBuf, u4InBufLen);
  825. break;
  826. case TDLS_FRM_ACTION_PTI_RSP:
  827. /* simulate to receive a PTI response frame */
  828. TdlsCmdTestPtiRspRecv(prGlueInfo, prInBuf, u4InBufLen);
  829. break;
  830. case TDLS_FRM_DATA_TEST_DATA:
  831. /* simulate to receive a DATA frame */
  832. TdlsCmdTestDataRecv(prGlueInfo, prInBuf, u4InBufLen);
  833. break;
  834. case TDLS_FRM_ACTION_CHAN_SWITCH_REQ:
  835. /* simulate to receive a channel switch request frame */
  836. TdlsCmdTestChSwReqRecv(prGlueInfo, prInBuf, u4InBufLen);
  837. break;
  838. case TDLS_FRM_ACTION_CHAN_SWITCH_RSP:
  839. /* simulate to receive a channel switch response frame */
  840. TdlsCmdTestChSwRspRecv(prGlueInfo, prInBuf, u4InBufLen);
  841. break;
  842. case TDLS_FRM_ACTION_DISCOVERY_REQ:
  843. /* simulate to receive a discovery request frame */
  844. TdlsCmdTestDiscoveryReqRecv(prGlueInfo, prInBuf, u4InBufLen);
  845. break;
  846. default:
  847. DBGLOG(TDLS, ERROR, "<tdls_cmd> wrong test rv frame sub command\n");
  848. return;
  849. }
  850. /* if (u4Status != TDLS_STATUS_SUCCESS) */
  851. {
  852. /* DBGLOG(TDLS, ERROR, ("<tdls_cmd> command parse fail\n")); */
  853. /* return; */
  854. }
  855. /* send command to wifi task to handle */
  856. #if 0
  857. kalIoctl(prGlueInfo,
  858. TdlsTestFrameSend,
  859. (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
  860. #endif
  861. }
  862. /*----------------------------------------------------------------------------*/
  863. /*! \brief This routine is called to receive a test setup confirm frame command.
  864. *
  865. * \param[in] prGlueInfo Pointer to the Adapter structure
  866. * \param[in] prInBuf A pointer to the command string buffer
  867. * \param[in] u4InBufLen The length of the buffer
  868. * \param[out] None
  869. *
  870. * \retval None
  871. *
  872. * EX: iwpriv wlan0 set_str_cmd 0_1_2_[DialogToken]_[StatusCode]_[Peer MAC]
  873. iwpriv wlan0 set_str_cmd 0_1_2_1_0_00:11:22:33:44:01
  874. */
  875. /*----------------------------------------------------------------------------*/
  876. static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  877. {
  878. ADAPTER_T *prAdapter;
  879. P_BSS_INFO_T prBssInfo;
  880. PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo;
  881. struct sk_buff *prMsduInfo;
  882. UINT_8 *pPkt;
  883. UINT_32 u4PktLen, u4IeLen;
  884. UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6];
  885. /* parse arguments */
  886. ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  887. ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  888. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
  889. DBGLOG(TDLS, INFO,
  890. "<tdls_fme> %s: DialogToken=%d StatusCode=%d from %pM\n",
  891. __func__, ucDialogToken, ucStatusCode, aucPeerMac);
  892. /* allocate/init packet */
  893. prAdapter = prGlueInfo->prAdapter;
  894. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  895. prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
  896. u4PktLen = 0;
  897. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  898. if (prMsduInfo == NULL) {
  899. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  900. return;
  901. }
  902. prMsduInfo->dev = prGlueInfo->prDevHandler;
  903. if (prMsduInfo->dev == NULL) {
  904. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  905. kalPacketFree(prGlueInfo, prMsduInfo);
  906. return;
  907. }
  908. /* make up frame content */
  909. /* 1. 802.3 header */
  910. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  911. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  912. kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
  913. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  914. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  915. LR_TDLS_FME_FIELD_FILL(2);
  916. /* 2. payload type */
  917. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  918. LR_TDLS_FME_FIELD_FILL(1);
  919. /* 3. Frame Formation - (1) Category */
  920. *pPkt = TDLS_FRM_CATEGORY;
  921. LR_TDLS_FME_FIELD_FILL(1);
  922. /* 3. Frame Formation - (2) Action */
  923. *pPkt = TDLS_FRM_ACTION_CONFIRM;
  924. LR_TDLS_FME_FIELD_FILL(1);
  925. /* 3. Frame Formation - (3) Status Code */
  926. *pPkt = ucStatusCode;
  927. *(pPkt + 1) = 0x00;
  928. LR_TDLS_FME_FIELD_FILL(2);
  929. /* 3. Frame Formation - (4) Dialog token */
  930. *pPkt = ucDialogToken;
  931. LR_TDLS_FME_FIELD_FILL(1);
  932. /* 3. Frame Formation - (17) WMM Information element */
  933. if (prAdapter->rWifiVar.fgSupportQoS) {
  934. u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE);
  935. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  936. }
  937. /* 3. Frame Formation - (16) Link identifier element */
  938. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  939. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
  940. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  941. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
  942. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
  943. u4IeLen = IE_SIZE(pPkt);
  944. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  945. /* 4. Update packet length */
  946. prMsduInfo->len = u4PktLen;
  947. dumpMemory8(prMsduInfo->data, u4PktLen);
  948. /* pass to OS */
  949. TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
  950. }
  951. /*----------------------------------------------------------------------------*/
  952. /*! \brief This routine is called to receive a test setup request frame command.
  953. *
  954. * \param[in] prGlueInfo Pointer to the Adapter structure
  955. * \param[in] prInBuf A pointer to the command string buffer
  956. * \param[in] u4InBufLen The length of the buffer
  957. * \param[out] None
  958. *
  959. * \retval None
  960. *
  961. * EX: iwpriv wlan0 set_str_cmd 0_1_0_[DialogToken]_[Peer MAC]_[BSSID]
  962. iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01
  963. iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01_00:22:33:44:11:22
  964. */
  965. /*----------------------------------------------------------------------------*/
  966. static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  967. {
  968. ADAPTER_T *prAdapter;
  969. P_BSS_INFO_T prBssInfo;
  970. struct sk_buff *prMsduInfo;
  971. UINT_8 *pPkt;
  972. UINT_32 u4PktLen, u4IeLen;
  973. UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6];
  974. UINT_16 u2CapInfo;
  975. /* parse arguments */
  976. ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  977. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
  978. kalMemZero(aucZeroMac, sizeof(aucZeroMac));
  979. kalMemZero(aucBSSID, sizeof(aucBSSID));
  980. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID);
  981. DBGLOG(TDLS, INFO,
  982. "<tdls_fme> %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac);
  983. /* allocate/init packet */
  984. prAdapter = prGlueInfo->prAdapter;
  985. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  986. u4PktLen = 0;
  987. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  988. if (prMsduInfo == NULL) {
  989. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  990. return;
  991. }
  992. prMsduInfo->dev = prGlueInfo->prDevHandler;
  993. if (prMsduInfo->dev == NULL) {
  994. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  995. kalPacketFree(prGlueInfo, prMsduInfo);
  996. return;
  997. }
  998. /* make up frame content */
  999. /* 1. 802.3 header */
  1000. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  1001. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1002. kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
  1003. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1004. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  1005. LR_TDLS_FME_FIELD_FILL(2);
  1006. /* 2. payload type */
  1007. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  1008. LR_TDLS_FME_FIELD_FILL(1);
  1009. /* 3. Frame Formation - (1) Category */
  1010. *pPkt = TDLS_FRM_CATEGORY;
  1011. LR_TDLS_FME_FIELD_FILL(1);
  1012. /* 3. Frame Formation - (2) Action */
  1013. *pPkt = TDLS_FRM_ACTION_SETUP_REQ;
  1014. LR_TDLS_FME_FIELD_FILL(1);
  1015. /* 3. Frame Formation - (3) Dialog token */
  1016. *pPkt = ucDialogToken;
  1017. LR_TDLS_FME_FIELD_FILL(1);
  1018. /* 3. Frame Formation - (4) Capability */
  1019. u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL);
  1020. WLAN_SET_FIELD_16(pPkt, u2CapInfo);
  1021. LR_TDLS_FME_FIELD_FILL(2);
  1022. /* 4. Append general IEs */
  1023. u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
  1024. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1025. /* 3. Frame Formation - (10) Extended capabilities element */
  1026. EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
  1027. EXT_CAP_IE(pPkt)->ucLength = 5;
  1028. EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
  1029. EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
  1030. EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
  1031. EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
  1032. EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
  1033. /* TDLS_EX_CAP_PEER_UAPSD */
  1034. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24));
  1035. /* TDLS_EX_CAP_CHAN_SWITCH */
  1036. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24));
  1037. /* TDLS_EX_CAP_TDLS */
  1038. EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32));
  1039. u4IeLen = IE_SIZE(pPkt);
  1040. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1041. /* 3. Frame Formation - (16) Link identifier element */
  1042. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  1043. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18;
  1044. if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0)
  1045. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  1046. else
  1047. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6);
  1048. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
  1049. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
  1050. u4IeLen = IE_SIZE(pPkt);
  1051. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1052. /* 4. Update packet length */
  1053. prMsduInfo->len = u4PktLen;
  1054. dumpMemory8(prMsduInfo->data, u4PktLen);
  1055. /* pass to OS */
  1056. TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
  1057. }
  1058. /*----------------------------------------------------------------------------*/
  1059. /*! \brief This routine is called to receive a test setup response frame command.
  1060. *
  1061. * \param[in] prGlueInfo Pointer to the Adapter structure
  1062. * \param[in] prInBuf A pointer to the command string buffer
  1063. * \param[in] u4InBufLen The length of the buffer
  1064. * \param[out] None
  1065. *
  1066. * \retval None
  1067. *
  1068. * EX: iwpriv wlan0 set_str_cmd 0_1_1_[DialogToken]_[StatusCode]_[Peer MAC]
  1069. iwpriv wlan0 set_str_cmd 0_1_1_1_0_00:11:22:33:44:01
  1070. */
  1071. /*----------------------------------------------------------------------------*/
  1072. static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1073. {
  1074. ADAPTER_T *prAdapter;
  1075. P_BSS_INFO_T prBssInfo;
  1076. struct sk_buff *prMsduInfo;
  1077. UINT_8 *pPkt;
  1078. UINT_32 u4PktLen, u4IeLen;
  1079. UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6];
  1080. UINT_16 u2CapInfo;
  1081. /* parse arguments */
  1082. ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1083. ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1084. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
  1085. DBGLOG(TDLS, INFO,
  1086. "<tdls_fme> %s: DialogToken=%d StatusCode=%d from %pM\n",
  1087. __func__, ucDialogToken, ucStatusCode, aucPeerMac);
  1088. /* allocate/init packet */
  1089. prAdapter = prGlueInfo->prAdapter;
  1090. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  1091. u4PktLen = 0;
  1092. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  1093. if (prMsduInfo == NULL) {
  1094. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  1095. return;
  1096. }
  1097. prMsduInfo->dev = prGlueInfo->prDevHandler;
  1098. if (prMsduInfo->dev == NULL) {
  1099. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  1100. kalPacketFree(prGlueInfo, prMsduInfo);
  1101. return;
  1102. }
  1103. /* make up frame content */
  1104. /* 1. 802.3 header */
  1105. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  1106. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1107. kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
  1108. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1109. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  1110. LR_TDLS_FME_FIELD_FILL(2);
  1111. /* 2. payload type */
  1112. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  1113. LR_TDLS_FME_FIELD_FILL(1);
  1114. /* 3. Frame Formation - (1) Category */
  1115. *pPkt = TDLS_FRM_CATEGORY;
  1116. LR_TDLS_FME_FIELD_FILL(1);
  1117. /* 3. Frame Formation - (2) Action */
  1118. *pPkt = TDLS_FRM_ACTION_SETUP_RSP;
  1119. LR_TDLS_FME_FIELD_FILL(1);
  1120. /* 3. Frame Formation - (3) Status Code */
  1121. *pPkt = ucStatusCode;
  1122. *(pPkt + 1) = 0x00;
  1123. LR_TDLS_FME_FIELD_FILL(2);
  1124. /* 3. Frame Formation - (4) Dialog token */
  1125. *pPkt = ucDialogToken;
  1126. LR_TDLS_FME_FIELD_FILL(1);
  1127. /* 3. Frame Formation - (5) Capability */
  1128. u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL);
  1129. WLAN_SET_FIELD_16(pPkt, u2CapInfo);
  1130. LR_TDLS_FME_FIELD_FILL(2);
  1131. /* 4. Append general IEs */
  1132. u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
  1133. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1134. /* 3. Frame Formation - (10) Extended capabilities element */
  1135. EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
  1136. EXT_CAP_IE(pPkt)->ucLength = 5;
  1137. EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
  1138. EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
  1139. EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
  1140. EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
  1141. EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
  1142. /* TDLS_EX_CAP_PEER_UAPSD */
  1143. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24));
  1144. /* TDLS_EX_CAP_CHAN_SWITCH */
  1145. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24));
  1146. /* TDLS_EX_CAP_TDLS */
  1147. EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32));
  1148. u4IeLen = IE_SIZE(pPkt);
  1149. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1150. /* 3. Frame Formation - (16) Link identifier element */
  1151. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  1152. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
  1153. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  1154. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
  1155. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6);
  1156. u4IeLen = IE_SIZE(pPkt);
  1157. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1158. /* 4. Update packet length */
  1159. prMsduInfo->len = u4PktLen;
  1160. dumpMemory8(prMsduInfo->data, u4PktLen);
  1161. /* pass to OS */
  1162. TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
  1163. }
  1164. /*----------------------------------------------------------------------------*/
  1165. /*! \brief This routine is called to inform firmware to skip channel switch timeout function.
  1166. *
  1167. * \param[in] prGlueInfo Pointer to the Adapter structure
  1168. * \param[in] prInBuf A pointer to the command string buffer
  1169. * \param[in] u4InBufLen The length of the buffer
  1170. * \param[out] None
  1171. *
  1172. * \retval None
  1173. *
  1174. * EX: iwpriv wlan0 set_str_cmd 0_14_[Enable/Disable]
  1175. iwpriv wlan0 set_str_cmd 0_14_0
  1176. */
  1177. /*----------------------------------------------------------------------------*/
  1178. static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1179. {
  1180. WLAN_STATUS rStatus;
  1181. TDLS_CMD_CORE_T rCmd;
  1182. UINT_32 u4BufLen;
  1183. /* parse arguments */
  1184. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  1185. rCmd.Content.rCmdScanSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1186. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdScanSkip.fgIsEnable);
  1187. /* command to do this */
  1188. rStatus = kalIoctl(prGlueInfo, TdlsTestScanSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  1189. if (rStatus != WLAN_STATUS_SUCCESS) {
  1190. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  1191. return;
  1192. }
  1193. }
  1194. /*----------------------------------------------------------------------------*/
  1195. /*! \brief This routine is called to receive a test tear down frame command.
  1196. *
  1197. * \param[in] prGlueInfo Pointer to the Adapter structure
  1198. * \param[in] prInBuf A pointer to the command string buffer
  1199. * \param[in] u4InBufLen The length of the buffer
  1200. * \param[out] None
  1201. *
  1202. * \retval None
  1203. *
  1204. * EX: iwpriv wlan0 set_str_cmd 0_1_3_[IsInitiator]_[ReasonCode]_[Peer MAC]_[Where]
  1205. Where 0 (From driver) or 1 (From FW)
  1206. iwpriv wlan0 set_str_cmd 0_1_3_1_26_00:11:22:33:44:01_0
  1207. */
  1208. /*----------------------------------------------------------------------------*/
  1209. static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1210. {
  1211. ADAPTER_T *prAdapter;
  1212. P_BSS_INFO_T prBssInfo;
  1213. struct sk_buff *prMsduInfo;
  1214. UINT_8 *pPkt;
  1215. UINT_32 u4PktLen, u4IeLen;
  1216. BOOLEAN fgIsInitiator;
  1217. UINT_8 ucReasonCode, aucPeerMac[6];
  1218. BOOLEAN fgIsFromWhich;
  1219. WLAN_STATUS rStatus;
  1220. TDLS_CMD_CORE_T rCmd;
  1221. UINT_32 u4BufLen;
  1222. /* parse arguments */
  1223. fgIsInitiator = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1224. ucReasonCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1225. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
  1226. fgIsFromWhich = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1227. DBGLOG(TDLS, INFO,
  1228. "<tdls_fme> %s: ReasonCode=%d from %pM %d\n",
  1229. __func__, ucReasonCode, aucPeerMac, fgIsFromWhich);
  1230. if (fgIsFromWhich == 0) {
  1231. /* allocate/init packet */
  1232. prAdapter = prGlueInfo->prAdapter;
  1233. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  1234. u4PktLen = 0;
  1235. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  1236. if (prMsduInfo == NULL) {
  1237. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  1238. return;
  1239. }
  1240. prMsduInfo->dev = prGlueInfo->prDevHandler;
  1241. if (prMsduInfo->dev == NULL) {
  1242. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  1243. kalPacketFree(prGlueInfo, prMsduInfo);
  1244. return;
  1245. }
  1246. /* make up frame content */
  1247. /* 1. 802.3 header */
  1248. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  1249. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1250. kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
  1251. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1252. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  1253. LR_TDLS_FME_FIELD_FILL(2);
  1254. /* 2. payload type */
  1255. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  1256. LR_TDLS_FME_FIELD_FILL(1);
  1257. /* 3. Frame Formation - (1) Category */
  1258. *pPkt = TDLS_FRM_CATEGORY;
  1259. LR_TDLS_FME_FIELD_FILL(1);
  1260. /* 3. Frame Formation - (2) Action */
  1261. *pPkt = TDLS_FRM_ACTION_TEARDOWN;
  1262. LR_TDLS_FME_FIELD_FILL(1);
  1263. /* 3. Frame Formation - (3) Reason Code */
  1264. *pPkt = ucReasonCode;
  1265. *(pPkt + 1) = 0x00;
  1266. LR_TDLS_FME_FIELD_FILL(2);
  1267. /* 3. Frame Formation - (16) Link identifier element */
  1268. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  1269. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
  1270. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  1271. if (fgIsInitiator == 1) {
  1272. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
  1273. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
  1274. } else {
  1275. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
  1276. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6);
  1277. }
  1278. u4IeLen = IE_SIZE(pPkt);
  1279. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1280. /* 4. Update packet length */
  1281. prMsduInfo->len = u4PktLen;
  1282. dumpMemory8(prMsduInfo->data, u4PktLen);
  1283. /* pass to OS */
  1284. TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
  1285. } else {
  1286. kalMemZero(&rCmd, sizeof(rCmd));
  1287. kalMemCopy(rCmd.aucPeerMac, aucPeerMac, 6);
  1288. rCmd.Content.rCmdTearDownRcv.u4ReasonCode = (UINT32) ucReasonCode;
  1289. /* command to do this */
  1290. rStatus = kalIoctl(prGlueInfo,
  1291. TdlsTestTearDownRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  1292. if (rStatus != WLAN_STATUS_SUCCESS) {
  1293. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  1294. return;
  1295. }
  1296. }
  1297. }
  1298. /*----------------------------------------------------------------------------*/
  1299. /*! \brief This routine is called to inform firmware to skip tx fail case.
  1300. *
  1301. * \param[in] prGlueInfo Pointer to the Adapter structure
  1302. * \param[in] prInBuf A pointer to the command string buffer
  1303. * \param[in] u4InBufLen The length of the buffer
  1304. * \param[out] None
  1305. *
  1306. * \retval None
  1307. *
  1308. * EX: iwpriv wlan0 set_str_cmd 0_7_[Enable/Disable]
  1309. iwpriv wlan0 set_str_cmd 0_7_1
  1310. */
  1311. /*----------------------------------------------------------------------------*/
  1312. static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1313. {
  1314. WLAN_STATUS rStatus;
  1315. TDLS_CMD_CORE_T rCmd;
  1316. UINT_32 u4BufLen;
  1317. /* parse arguments */
  1318. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  1319. rCmd.Content.rCmdTxFailSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1320. DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdTxFailSkip.fgIsEnable);
  1321. /* command to do this */
  1322. rStatus = kalIoctl(prGlueInfo, TdlsTestTxFailSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  1323. if (rStatus != WLAN_STATUS_SUCCESS) {
  1324. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  1325. return;
  1326. }
  1327. }
  1328. /*----------------------------------------------------------------------------*/
  1329. /*! \brief This routine is called to send a test frame command to wifi task.
  1330. *
  1331. * \param[in] prGlueInfo Pointer to the Adapter structure
  1332. * \param[in] prInBuf A pointer to the command string buffer
  1333. * \param[in] u4InBufLen The length of the buffer
  1334. * \param[out] None
  1335. *
  1336. * \retval None
  1337. *
  1338. * EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC]
  1339. iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01
  1340. *
  1341. * EX: iwpriv wlan0 set_str_cmd 0_12_2_[FrameType]_[DialogToken]_[Peer MAC]
  1342. iwpriv wlan0 set_str_cmd 0_12_2_0_1_00:11:22:33:44:01
  1343. */
  1344. /*----------------------------------------------------------------------------*/
  1345. static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1346. {
  1347. PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd;
  1348. UINT32 u4Subcmd;
  1349. UINT_32 u4BufLen;
  1350. /* parse sub-command */
  1351. u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1352. DBGLOG(TDLS, INFO, "<tdls_cmd> test tx tdls frame sub command = %u\n", u4Subcmd);
  1353. /* parse command arguments */
  1354. rCmd.ucFmeType = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen);
  1355. switch (u4Subcmd) {
  1356. case TDLS_FRM_ACTION_SETUP_REQ:
  1357. case TDLS_FRM_ACTION_SETUP_RSP:
  1358. case TDLS_FRM_ACTION_CONFIRM:
  1359. rCmd.ucToken = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen);
  1360. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
  1361. DBGLOG(TDLS, INFO, "<tdls_cmd> setup FmeType=%d Token=%d to [%pM]\n",
  1362. rCmd.ucFmeType, rCmd.ucToken, rCmd.arRspAddr);
  1363. break;
  1364. default:
  1365. DBGLOG(TDLS, ERROR, "<tdls_cmd> wrong test tx frame sub command\n");
  1366. return;
  1367. }
  1368. /* send command to wifi task to handle */
  1369. kalIoctl(prGlueInfo,
  1370. TdlsTestTdlsFrameSend,
  1371. (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
  1372. }
  1373. /*----------------------------------------------------------------------------*/
  1374. /*! \brief This routine is called to send a test frame command to wifi task.
  1375. *
  1376. * \param[in] prGlueInfo Pointer to the Adapter structure
  1377. * \param[in] prInBuf A pointer to the command string buffer
  1378. * \param[in] u4InBufLen The length of the buffer
  1379. * \param[out] None
  1380. *
  1381. * \retval None
  1382. *
  1383. * EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_
  1384. [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_
  1385. [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_
  1386. [Timeout]_[Peer MAC]
  1387. iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01
  1388. */
  1389. /*----------------------------------------------------------------------------*/
  1390. static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1391. {
  1392. PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd;
  1393. TDLS_STATUS u4Status;
  1394. UINT_32 u4Subcmd;
  1395. UINT_32 u4BufLen;
  1396. /* parse sub-command */
  1397. u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1398. DBGLOG(TDLS, INFO, "<tdls_cmd> test tx frame sub command = %u\n", (UINT32) u4Subcmd);
  1399. /* parse command arguments */
  1400. switch (u4Subcmd) {
  1401. case TDLS_FRM_ACTION_SETUP_REQ:
  1402. u4Status = TdlsCmdTestTxFmeSetupReqBufTranslate(prInBuf, u4InBufLen, &rCmd);
  1403. break;
  1404. default:
  1405. DBGLOG(TDLS, ERROR, "<tdls_cmd> wrong test tx frame sub command\n");
  1406. return;
  1407. }
  1408. if (u4Status != TDLS_STATUS_SUCCESS) {
  1409. DBGLOG(TDLS, ERROR, "<tdls_cmd> command parse fail\n");
  1410. return;
  1411. }
  1412. /* send command to wifi task to handle */
  1413. kalIoctl(prGlueInfo,
  1414. TdlsTestFrameSend,
  1415. (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
  1416. }
  1417. /*----------------------------------------------------------------------------*/
  1418. /*!
  1419. * @brief Parse the TDLS test frame command, setup request
  1420. *
  1421. * @param CmdBuf Pointer to the buffer.
  1422. * @param BufLen Record buffer length.
  1423. * @param CmdTspec Pointer to the structure.
  1424. *
  1425. * @retval WLAN_STATUS_SUCCESS: Translate OK.
  1426. * @retval WLAN_STATUS_FAILURE: Translate fail.
  1427. * @usage iwpriv wlan0 set_str_cmd [tdls]_[command]
  1428. *
  1429. * EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_
  1430. [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_
  1431. [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_
  1432. [Timeout]_[Peer MAC]
  1433. iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01
  1434. */
  1435. /*----------------------------------------------------------------------------*/
  1436. static TDLS_STATUS
  1437. TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd)
  1438. {
  1439. /* dumpMemory8(ANDROID_LOG_INFO, pCmdBuf, u4BufLen); */
  1440. prCmd->ucFmeType = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1441. prCmd->ucToken = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1442. prCmd->u2Cap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1443. prCmd->ucExCap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1444. prCmd->arSupRate[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1445. prCmd->arSupRate[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1446. prCmd->arSupRate[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1447. prCmd->arSupRate[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1448. prCmd->arSupChan[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1449. prCmd->arSupChan[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1450. prCmd->arSupChan[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1451. prCmd->arSupChan[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1452. prCmd->u4Timeout = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
  1453. CmdStringMacParse(pCmdBuf, &pCmdBuf, &u4BufLen, prCmd->arRspAddr);
  1454. DBGLOG(TDLS, INFO, "<tdls_cmd> command content =\n");
  1455. DBGLOG(TDLS, INFO, "\tPeer MAC = %pM\n", (prCmd->arRspAddr));
  1456. DBGLOG(TDLS, INFO, "\tToken = %u, Cap = 0x%x, ExCap = 0x%x, Timeout = %us FrameType = %u\n",
  1457. (UINT32) prCmd->ucToken, prCmd->u2Cap, prCmd->ucExCap,
  1458. (UINT32) prCmd->u4Timeout, (UINT32) prCmd->ucFmeType);
  1459. DBGLOG(TDLS, INFO, "\tSupRate = 0x%x %x %x %x\n",
  1460. prCmd->arSupRate[0], prCmd->arSupRate[1], prCmd->arSupRate[2], prCmd->arSupRate[3]);
  1461. DBGLOG(TDLS, INFO, "\tSupChan = %d %d %d %d\n",
  1462. prCmd->arSupChan[0], prCmd->arSupChan[1], prCmd->arSupChan[2], prCmd->arSupChan[3]);
  1463. return TDLS_STATUS_SUCCESS;
  1464. }
  1465. /*----------------------------------------------------------------------------*/
  1466. /*! \brief This routine is called to update a TDLS peer.
  1467. *
  1468. * \param[in] prGlueInfo Pointer to the Adapter structure
  1469. * \param[in] prInBuf A pointer to the command string buffer
  1470. * \param[in] u4InBufLen The length of the buffer
  1471. * \param[out] None
  1472. *
  1473. * \retval None
  1474. *
  1475. * EX: iwpriv wlan0 set_str_cmd 0_3_[Responder MAC]
  1476. iwpriv wlan0 set_str_cmd 0_3_00:11:22:33:44:01
  1477. */
  1478. /*----------------------------------------------------------------------------*/
  1479. static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1480. {
  1481. PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd;
  1482. struct wireless_dev *prWdev;
  1483. /* reset */
  1484. kalMemZero(&rCmd, sizeof(rCmd));
  1485. /* parse arguments */
  1486. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
  1487. /* init */
  1488. rCmd.rPeerInfo.supported_rates = rCmd.arSupRate;
  1489. rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa;
  1490. rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */
  1491. rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER);
  1492. rCmd.rPeerInfo.uapsd_queues = 0xf; /* all AC */
  1493. rCmd.rPeerInfo.max_sp = 0; /* delivery all packets */
  1494. /* send command to wifi task to handle */
  1495. prWdev = prGlueInfo->prDevHandler->ieee80211_ptr;
  1496. mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo);
  1497. /* update */
  1498. TdlsexCfg80211TdlsOper(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, NL80211_TDLS_ENABLE_LINK);
  1499. }
  1500. /*----------------------------------------------------------------------------*/
  1501. /*! \brief This routine is called to receive a Null frame from the peer.
  1502. *
  1503. * \param[in] prAdapter Pointer to the Adapter structure
  1504. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1505. * \param[in] u4SetBufferLen The length of the set buffer
  1506. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1507. * bytes read from the set buffer. If the call failed due to invalid length of
  1508. * the set buffer, returns the amount of storage needed.
  1509. *
  1510. * \retval TDLS_STATUS_xx
  1511. *
  1512. * EX: iwpriv wlan0 set_str_cmd 0_5_[Responder MAC]_[PM bit]
  1513. iwpriv wlan0 set_str_cmd 0_5_00:11:22:33:44:01_1
  1514. */
  1515. /*----------------------------------------------------------------------------*/
  1516. static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  1517. {
  1518. WLAN_STATUS rStatus;
  1519. TDLS_CMD_CORE_T rCmd;
  1520. UINT_32 u4BufLen;
  1521. /* parse arguments */
  1522. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  1523. rCmd.Content.rCmdNullRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  1524. DBGLOG(TDLS, INFO, "%s: [%pM] u4PM = %u\n",
  1525. __func__, (rCmd.aucPeerMac), (UINT32) rCmd.Content.rCmdNullRcv.u4PM);
  1526. /* command to do this */
  1527. rStatus = kalIoctl(prGlueInfo, TdlsTestNullRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  1528. if (rStatus != WLAN_STATUS_SUCCESS) {
  1529. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  1530. return;
  1531. }
  1532. }
  1533. /*----------------------------------------------------------------------------*/
  1534. /*! \brief This routine is called to send a data frame to the peer periodically.
  1535. *
  1536. * \param[in] prAdapter Pointer to the Adapter structure
  1537. * \param[in] u4Param no use
  1538. * \param[out] None
  1539. *
  1540. * \retval None
  1541. *
  1542. * EX: iwpriv wlan0 set_str_cmd 0_15_[Responder MAC]_[Interval: ms]_[Enable/Disable]
  1543. iwpriv wlan0 set_str_cmd 0_15_00:11:22:33:44:01_5000_1
  1544. */
  1545. /*----------------------------------------------------------------------------*/
  1546. static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param)
  1547. {
  1548. GLUE_INFO_T *prGlueInfo;
  1549. struct sk_buff *prMsduInfo;
  1550. UINT_8 *prPkt;
  1551. /* init */
  1552. prGlueInfo = prAdapter->prGlueInfo;
  1553. /* allocate a data frame */
  1554. prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt);
  1555. if (prMsduInfo == NULL) {
  1556. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s allocate pkt fail!\n", __func__);
  1557. return;
  1558. }
  1559. /* init dev */
  1560. prMsduInfo->dev = prGlueInfo->prDevHandler;
  1561. if (prMsduInfo->dev == NULL) {
  1562. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s prMsduInfo->dev == NULL!\n", __func__);
  1563. kalPacketFree(prGlueInfo, prMsduInfo);
  1564. return;
  1565. }
  1566. /* init packet */
  1567. prMsduInfo->len = 1000;
  1568. kalMemCopy(prMsduInfo->data, aucTdlsTestDataSPeerMac, 6);
  1569. kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6);
  1570. *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800;
  1571. DBGLOG(TDLS, INFO, "<tdls_cmd> %s try to send a data frame to %pM\n",
  1572. __func__, aucTdlsTestDataSPeerMac);
  1573. /* simulate OS to send the packet */
  1574. wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
  1575. /* restart test timer */
  1576. cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval);
  1577. }
  1578. /*----------------------------------------------------------------------------*/
  1579. /*! \brief This routine is called to receive a Channel Switch Request frame.
  1580. *
  1581. * \param[in] prAdapter Pointer to the Adapter structure
  1582. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1583. * \param[in] u4SetBufferLen The length of the set buffer
  1584. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1585. * bytes read from the set buffer. If the call failed due to invalid length of
  1586. * the set buffer, returns the amount of storage needed.
  1587. *
  1588. * \retval TDLS_STATUS_xx
  1589. *
  1590. */
  1591. /*----------------------------------------------------------------------------*/
  1592. static TDLS_STATUS
  1593. TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1594. {
  1595. TDLS_CMD_CORE_T *prCmdContent;
  1596. WLAN_STATUS rStatus;
  1597. /* init command buffer */
  1598. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1599. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_REQ;
  1600. /* send the command */
  1601. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1602. CMD_ID_TDLS_CORE, /* ucCID */
  1603. TRUE, /* fgSetQuery */
  1604. FALSE, /* fgNeedResp */
  1605. FALSE, /* fgIsOid */
  1606. NULL, NULL, /* pfCmdTimeoutHandler */
  1607. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1608. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1609. NULL, /* pvSetQueryBuffer */
  1610. 0 /* u4SetQueryBufferLen */
  1611. );
  1612. if (rStatus != WLAN_STATUS_PENDING) {
  1613. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1614. return TDLS_STATUS_RESOURCES;
  1615. }
  1616. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1617. return TDLS_STATUS_SUCCESS;
  1618. }
  1619. /*----------------------------------------------------------------------------*/
  1620. /*! \brief This routine is called to receive a Channel Switch Response frame.
  1621. *
  1622. * \param[in] prAdapter Pointer to the Adapter structure
  1623. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1624. * \param[in] u4SetBufferLen The length of the set buffer
  1625. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1626. * bytes read from the set buffer. If the call failed due to invalid length of
  1627. * the set buffer, returns the amount of storage needed.
  1628. *
  1629. * \retval TDLS_STATUS_xx
  1630. *
  1631. */
  1632. /*----------------------------------------------------------------------------*/
  1633. static TDLS_STATUS
  1634. TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1635. {
  1636. TDLS_CMD_CORE_T *prCmdContent;
  1637. WLAN_STATUS rStatus;
  1638. /* init command buffer */
  1639. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1640. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_RSP;
  1641. /* send the command */
  1642. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1643. CMD_ID_TDLS_CORE, /* ucCID */
  1644. TRUE, /* fgSetQuery */
  1645. FALSE, /* fgNeedResp */
  1646. FALSE, /* fgIsOid */
  1647. NULL, NULL, /* pfCmdTimeoutHandler */
  1648. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1649. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1650. NULL, /* pvSetQueryBuffer */
  1651. 0 /* u4SetQueryBufferLen */
  1652. );
  1653. if (rStatus != WLAN_STATUS_PENDING) {
  1654. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1655. return TDLS_STATUS_RESOURCES;
  1656. }
  1657. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1658. return TDLS_STATUS_SUCCESS;
  1659. }
  1660. /*----------------------------------------------------------------------------*/
  1661. /*!
  1662. * \brief This routine is called to send a test frame.
  1663. *
  1664. * \param[in] prAdapter Pointer to the Adapter structure
  1665. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1666. * \param[in] u4SetBufferLen The length of the set buffer
  1667. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1668. * bytes read from the set buffer. If the call failed due to invalid length of
  1669. * the set buffer, returns the amount of storage needed.
  1670. *
  1671. * \retval TDLS_STATUS_xx
  1672. *
  1673. */
  1674. /*----------------------------------------------------------------------------*/
  1675. static TDLS_STATUS
  1676. TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1677. {
  1678. GLUE_INFO_T *prGlueInfo;
  1679. PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd;
  1680. P_BSS_INFO_T prBssInfo;
  1681. struct sk_buff *prMsduInfo;
  1682. UINT_8 *pPkt;
  1683. UINT_32 u4PktLen, u4IeLen;
  1684. /* sanity check */
  1685. ASSERT(prAdapter);
  1686. ASSERT(pvSetBuffer);
  1687. ASSERT(pu4SetInfoLen);
  1688. DBGLOG(TDLS, INFO, "<tdls_fme> %s\n", __func__);
  1689. if (u4SetBufferLen == 0)
  1690. return TDLS_STATUS_INVALID_LENGTH;
  1691. /* allocate/init packet */
  1692. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  1693. prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer;
  1694. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  1695. *pu4SetInfoLen = u4SetBufferLen;
  1696. u4PktLen = 0;
  1697. prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
  1698. if (prMsduInfo == NULL) {
  1699. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: allocate pkt fail\n", __func__);
  1700. return TDLS_STATUS_RESOURCES;
  1701. }
  1702. prMsduInfo->dev = prGlueInfo->prDevHandler;
  1703. if (prMsduInfo->dev == NULL) {
  1704. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: MsduInfo->dev == NULL\n", __func__);
  1705. kalPacketFree(prGlueInfo, prMsduInfo);
  1706. return TDLS_STATUS_FAILURE;
  1707. }
  1708. /* make up frame content */
  1709. /* 1. 802.3 header */
  1710. kalMemCopy(pPkt, prCmd->arRspAddr, TDLS_FME_MAC_ADDR_LEN);
  1711. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1712. kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
  1713. LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
  1714. *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE);
  1715. LR_TDLS_FME_FIELD_FILL(2);
  1716. /* 2. payload type */
  1717. *pPkt = TDLS_FRM_PAYLOAD_TYPE;
  1718. LR_TDLS_FME_FIELD_FILL(1);
  1719. /* 3. Frame Formation - (1) Category */
  1720. *pPkt = TDLS_FRM_CATEGORY;
  1721. LR_TDLS_FME_FIELD_FILL(1);
  1722. /* 3. Frame Formation - (2) Action */
  1723. *pPkt = prCmd->ucFmeType;
  1724. LR_TDLS_FME_FIELD_FILL(1);
  1725. /* 3. Frame Formation - (3) Dialog token */
  1726. *pPkt = prCmd->ucToken;
  1727. LR_TDLS_FME_FIELD_FILL(1);
  1728. /* 3. Frame Formation - (4) Capability */
  1729. WLAN_SET_FIELD_16(pPkt, prCmd->u2Cap);
  1730. LR_TDLS_FME_FIELD_FILL(2);
  1731. /* 4. Append general IEs */
  1732. u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
  1733. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1734. /* 3. Frame Formation - (10) Extended capabilities element */
  1735. EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
  1736. EXT_CAP_IE(pPkt)->ucLength = 5;
  1737. EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
  1738. EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
  1739. EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
  1740. EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
  1741. EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
  1742. if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD)
  1743. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24));
  1744. if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH)
  1745. EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24));
  1746. if (prCmd->ucExCap & TDLS_EX_CAP_TDLS)
  1747. EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32));
  1748. u4IeLen = IE_SIZE(pPkt);
  1749. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1750. /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */
  1751. TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL;
  1752. TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5;
  1753. TIMEOUT_INTERVAL_IE(pPkt)->ucType = IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME;
  1754. TIMEOUT_INTERVAL_IE(pPkt)->u4Value = htonl(prCmd->u4Timeout);
  1755. u4IeLen = IE_SIZE(pPkt);
  1756. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1757. /* 3. Frame Formation - (16) Link identifier element */
  1758. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
  1759. TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
  1760. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
  1761. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
  1762. kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prCmd->arRspAddr, 6);
  1763. u4IeLen = IE_SIZE(pPkt);
  1764. LR_TDLS_FME_FIELD_FILL(u4IeLen);
  1765. /* 4. Update packet length */
  1766. prMsduInfo->len = u4PktLen;
  1767. dumpMemory8(prMsduInfo->data, u4PktLen);
  1768. /* 5. send the data frame */
  1769. wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
  1770. return TDLS_STATUS_SUCCESS;
  1771. }
  1772. /*----------------------------------------------------------------------------*/
  1773. /*! \brief This routine is called to receive a NULL frame.
  1774. *
  1775. * \param[in] prAdapter Pointer to the Adapter structure
  1776. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1777. * \param[in] u4SetBufferLen The length of the set buffer
  1778. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1779. * bytes read from the set buffer. If the call failed due to invalid length of
  1780. * the set buffer, returns the amount of storage needed.
  1781. *
  1782. * \retval TDLS_STATUS_xx
  1783. *
  1784. */
  1785. /*----------------------------------------------------------------------------*/
  1786. static TDLS_STATUS
  1787. TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1788. {
  1789. TDLS_CMD_CORE_T *prCmdContent;
  1790. WLAN_STATUS rStatus;
  1791. /* init command buffer */
  1792. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1793. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_NULL_RCV;
  1794. /* send the command */
  1795. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1796. CMD_ID_TDLS_CORE, /* ucCID */
  1797. TRUE, /* fgSetQuery */
  1798. FALSE, /* fgNeedResp */
  1799. FALSE, /* fgIsOid */
  1800. NULL, NULL, /* pfCmdTimeoutHandler */
  1801. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1802. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1803. NULL, /* pvSetQueryBuffer */
  1804. 0 /* u4SetQueryBufferLen */
  1805. );
  1806. if (rStatus != WLAN_STATUS_PENDING) {
  1807. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1808. return TDLS_STATUS_RESOURCES;
  1809. }
  1810. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1811. return TDLS_STATUS_SUCCESS;
  1812. }
  1813. /*----------------------------------------------------------------------------*/
  1814. /*! \brief This routine is called to receive a PTI frame.
  1815. *
  1816. * \param[in] prAdapter Pointer to the Adapter structure
  1817. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1818. * \param[in] u4SetBufferLen The length of the set buffer
  1819. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1820. * bytes read from the set buffer. If the call failed due to invalid length of
  1821. * the set buffer, returns the amount of storage needed.
  1822. *
  1823. * \retval TDLS_STATUS_xx
  1824. *
  1825. */
  1826. /*----------------------------------------------------------------------------*/
  1827. static TDLS_STATUS
  1828. TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1829. {
  1830. TDLS_CMD_CORE_T *prCmdContent;
  1831. WLAN_STATUS rStatus;
  1832. /* init command buffer */
  1833. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1834. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_REQ;
  1835. /* send the command */
  1836. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1837. CMD_ID_TDLS_CORE, /* ucCID */
  1838. TRUE, /* fgSetQuery */
  1839. FALSE, /* fgNeedResp */
  1840. FALSE, /* fgIsOid */
  1841. NULL, NULL, /* pfCmdTimeoutHandler */
  1842. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1843. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1844. NULL, /* pvSetQueryBuffer */
  1845. 0 /* u4SetQueryBufferLen */
  1846. );
  1847. if (rStatus != WLAN_STATUS_PENDING) {
  1848. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1849. return TDLS_STATUS_RESOURCES;
  1850. }
  1851. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1852. return TDLS_STATUS_SUCCESS;
  1853. }
  1854. /*----------------------------------------------------------------------------*/
  1855. /*! \brief This routine is called to receive a PTI response frame.
  1856. *
  1857. * \param[in] prAdapter Pointer to the Adapter structure
  1858. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1859. * \param[in] u4SetBufferLen The length of the set buffer
  1860. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1861. * bytes read from the set buffer. If the call failed due to invalid length of
  1862. * the set buffer, returns the amount of storage needed.
  1863. *
  1864. * \retval TDLS_STATUS_xx
  1865. *
  1866. */
  1867. /*----------------------------------------------------------------------------*/
  1868. static TDLS_STATUS
  1869. TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1870. {
  1871. TDLS_CMD_CORE_T *prCmdContent;
  1872. WLAN_STATUS rStatus;
  1873. /* init command buffer */
  1874. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1875. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_RSP;
  1876. /* send the command */
  1877. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1878. CMD_ID_TDLS_CORE, /* ucCID */
  1879. TRUE, /* fgSetQuery */
  1880. FALSE, /* fgNeedResp */
  1881. FALSE, /* fgIsOid */
  1882. NULL, NULL, /* pfCmdTimeoutHandler */
  1883. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1884. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1885. NULL, /* pvSetQueryBuffer */
  1886. 0 /* u4SetQueryBufferLen */
  1887. );
  1888. if (rStatus != WLAN_STATUS_PENDING) {
  1889. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1890. return TDLS_STATUS_RESOURCES;
  1891. }
  1892. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1893. return TDLS_STATUS_SUCCESS;
  1894. }
  1895. /*----------------------------------------------------------------------------*/
  1896. /*! \brief This routine is called to receive a Tear Down frame.
  1897. *
  1898. * \param[in] prAdapter Pointer to the Adapter structure
  1899. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1900. * \param[in] u4SetBufferLen The length of the set buffer
  1901. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1902. * bytes read from the set buffer. If the call failed due to invalid length of
  1903. * the set buffer, returns the amount of storage needed.
  1904. *
  1905. * \retval TDLS_STATUS_xx
  1906. *
  1907. */
  1908. /*----------------------------------------------------------------------------*/
  1909. static TDLS_STATUS
  1910. TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1911. {
  1912. TDLS_CMD_CORE_T *prCmdContent;
  1913. WLAN_STATUS rStatus;
  1914. /* init command buffer */
  1915. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1916. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TEAR_DOWN;
  1917. /* send the command */
  1918. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1919. CMD_ID_TDLS_CORE, /* ucCID */
  1920. TRUE, /* fgSetQuery */
  1921. FALSE, /* fgNeedResp */
  1922. FALSE, /* fgIsOid */
  1923. NULL, NULL, /* pfCmdTimeoutHandler */
  1924. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1925. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1926. NULL, /* pvSetQueryBuffer */
  1927. 0 /* u4SetQueryBufferLen */
  1928. );
  1929. if (rStatus != WLAN_STATUS_PENDING) {
  1930. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1931. return TDLS_STATUS_RESOURCES;
  1932. }
  1933. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1934. return TDLS_STATUS_SUCCESS;
  1935. }
  1936. /*----------------------------------------------------------------------------*/
  1937. /*! \brief This routine is called to receive a data frame.
  1938. *
  1939. * \param[in] prAdapter Pointer to the Adapter structure
  1940. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1941. * \param[in] u4SetBufferLen The length of the set buffer
  1942. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1943. * bytes read from the set buffer. If the call failed due to invalid length of
  1944. * the set buffer, returns the amount of storage needed.
  1945. *
  1946. * \retval TDLS_STATUS_xx
  1947. *
  1948. */
  1949. /*----------------------------------------------------------------------------*/
  1950. static TDLS_STATUS
  1951. TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1952. {
  1953. TDLS_CMD_CORE_T *prCmdContent;
  1954. WLAN_STATUS rStatus;
  1955. /* init command buffer */
  1956. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1957. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_DATA_RCV;
  1958. /* send the command */
  1959. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  1960. CMD_ID_TDLS_CORE, /* ucCID */
  1961. TRUE, /* fgSetQuery */
  1962. FALSE, /* fgNeedResp */
  1963. FALSE, /* fgIsOid */
  1964. NULL, NULL, /* pfCmdTimeoutHandler */
  1965. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  1966. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  1967. NULL, /* pvSetQueryBuffer */
  1968. 0 /* u4SetQueryBufferLen */
  1969. );
  1970. if (rStatus != WLAN_STATUS_PENDING) {
  1971. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  1972. return TDLS_STATUS_RESOURCES;
  1973. }
  1974. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  1975. return TDLS_STATUS_SUCCESS;
  1976. }
  1977. /*----------------------------------------------------------------------------*/
  1978. /*! \brief This routine is called to skip PTI tx fail status.
  1979. *
  1980. * \param[in] prAdapter Pointer to the Adapter structure
  1981. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  1982. * \param[in] u4SetBufferLen The length of the set buffer
  1983. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  1984. * bytes read from the set buffer. If the call failed due to invalid length of
  1985. * the set buffer, returns the amount of storage needed.
  1986. *
  1987. * \retval TDLS_STATUS_xx
  1988. *
  1989. */
  1990. /*----------------------------------------------------------------------------*/
  1991. static TDLS_STATUS
  1992. TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  1993. {
  1994. TDLS_CMD_CORE_T *prCmdContent;
  1995. WLAN_STATUS rStatus;
  1996. /* init command buffer */
  1997. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  1998. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_TX_FAIL;
  1999. /* send the command */
  2000. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2001. CMD_ID_TDLS_CORE, /* ucCID */
  2002. TRUE, /* fgSetQuery */
  2003. FALSE, /* fgNeedResp */
  2004. FALSE, /* fgIsOid */
  2005. NULL, NULL, /* pfCmdTimeoutHandler */
  2006. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2007. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2008. NULL, /* pvSetQueryBuffer */
  2009. 0 /* u4SetQueryBufferLen */
  2010. );
  2011. if (rStatus != WLAN_STATUS_PENDING) {
  2012. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2013. return TDLS_STATUS_RESOURCES;
  2014. }
  2015. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2016. return TDLS_STATUS_SUCCESS;
  2017. }
  2018. /*----------------------------------------------------------------------------*/
  2019. /*!
  2020. * \brief This routine is called to send a TDLS action frame.
  2021. *
  2022. * \param[in] prAdapter Pointer to the Adapter structure
  2023. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2024. * \param[in] u4SetBufferLen The length of the set buffer
  2025. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2026. * bytes read from the set buffer. If the call failed due to invalid length of
  2027. * the set buffer, returns the amount of storage needed.
  2028. *
  2029. * \retval TDLS_STATUS_xx
  2030. *
  2031. * EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC]
  2032. iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01
  2033. */
  2034. /*----------------------------------------------------------------------------*/
  2035. static TDLS_STATUS
  2036. TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2037. {
  2038. GLUE_INFO_T *prGlueInfo;
  2039. PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd;
  2040. struct wireless_dev *prWdev;
  2041. /* sanity check */
  2042. ASSERT(prAdapter);
  2043. ASSERT(pvSetBuffer);
  2044. ASSERT(pu4SetInfoLen);
  2045. DBGLOG(TDLS, INFO, "<tdls_fme> %s\n", __func__);
  2046. if (u4SetBufferLen == 0)
  2047. return TDLS_STATUS_INVALID_LENGTH;
  2048. /* allocate/init packet */
  2049. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  2050. prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer;
  2051. prWdev = (struct wireless_dev *)prGlueInfo->prDevHandler->ieee80211_ptr;
  2052. TdlsexCfg80211TdlsMgmt(prWdev->wiphy, NULL,
  2053. prCmd->arRspAddr, prCmd->ucFmeType, 1,
  2054. 0, 0, /* open/none */
  2055. FALSE, NULL, 0);
  2056. return TDLS_STATUS_SUCCESS;
  2057. }
  2058. /*----------------------------------------------------------------------------*/
  2059. /*! \brief This routine is called to skip tx fail status. So always success in tx done in firmware.
  2060. *
  2061. * \param[in] prAdapter Pointer to the Adapter structure
  2062. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2063. * \param[in] u4SetBufferLen The length of the set buffer
  2064. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2065. * bytes read from the set buffer. If the call failed due to invalid length of
  2066. * the set buffer, returns the amount of storage needed.
  2067. *
  2068. * \retval TDLS_STATUS_xx
  2069. *
  2070. */
  2071. /*----------------------------------------------------------------------------*/
  2072. static TDLS_STATUS
  2073. TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2074. {
  2075. TDLS_CMD_CORE_T *prCmdContent;
  2076. WLAN_STATUS rStatus;
  2077. /* init command buffer */
  2078. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2079. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TX_FAIL_SKIP;
  2080. /* send the command */
  2081. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2082. CMD_ID_TDLS_CORE, /* ucCID */
  2083. TRUE, /* fgSetQuery */
  2084. FALSE, /* fgNeedResp */
  2085. FALSE, /* fgIsOid */
  2086. NULL, NULL, /* pfCmdTimeoutHandler */
  2087. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2088. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2089. NULL, /* pvSetQueryBuffer */
  2090. 0 /* u4SetQueryBufferLen */
  2091. );
  2092. if (rStatus != WLAN_STATUS_PENDING) {
  2093. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2094. return TDLS_STATUS_RESOURCES;
  2095. }
  2096. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2097. return TDLS_STATUS_SUCCESS;
  2098. }
  2099. /*----------------------------------------------------------------------------*/
  2100. /*! \brief This routine is called to skip to do keep alive function in firmware.
  2101. *
  2102. * \param[in] prAdapter Pointer to the Adapter structure
  2103. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2104. * \param[in] u4SetBufferLen The length of the set buffer
  2105. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2106. * bytes read from the set buffer. If the call failed due to invalid length of
  2107. * the set buffer, returns the amount of storage needed.
  2108. *
  2109. * \retval TDLS_STATUS_xx
  2110. *
  2111. */
  2112. /*----------------------------------------------------------------------------*/
  2113. static TDLS_STATUS
  2114. TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2115. {
  2116. TDLS_CMD_CORE_T *prCmdContent;
  2117. WLAN_STATUS rStatus;
  2118. /* init command buffer */
  2119. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2120. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP;
  2121. /* send the command */
  2122. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2123. CMD_ID_TDLS_CORE, /* ucCID */
  2124. TRUE, /* fgSetQuery */
  2125. FALSE, /* fgNeedResp */
  2126. FALSE, /* fgIsOid */
  2127. NULL, NULL, /* pfCmdTimeoutHandler */
  2128. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2129. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2130. NULL, /* pvSetQueryBuffer */
  2131. 0 /* u4SetQueryBufferLen */
  2132. );
  2133. if (rStatus != WLAN_STATUS_PENDING) {
  2134. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2135. return TDLS_STATUS_RESOURCES;
  2136. }
  2137. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2138. return TDLS_STATUS_SUCCESS;
  2139. }
  2140. /*----------------------------------------------------------------------------*/
  2141. /*! \brief This routine is called to skip channel switch timeout.
  2142. *
  2143. * \param[in] prAdapter Pointer to the Adapter structure
  2144. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2145. * \param[in] u4SetBufferLen The length of the set buffer
  2146. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2147. * bytes read from the set buffer. If the call failed due to invalid length of
  2148. * the set buffer, returns the amount of storage needed.
  2149. *
  2150. * \retval TDLS_STATUS_xx
  2151. *
  2152. */
  2153. /*----------------------------------------------------------------------------*/
  2154. static TDLS_STATUS
  2155. TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2156. {
  2157. TDLS_CMD_CORE_T *prCmdContent;
  2158. WLAN_STATUS rStatus;
  2159. /* init command buffer */
  2160. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2161. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP;
  2162. /* send the command */
  2163. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2164. CMD_ID_TDLS_CORE, /* ucCID */
  2165. TRUE, /* fgSetQuery */
  2166. FALSE, /* fgNeedResp */
  2167. FALSE, /* fgIsOid */
  2168. NULL, NULL, /* pfCmdTimeoutHandler */
  2169. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2170. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2171. NULL, /* pvSetQueryBuffer */
  2172. 0 /* u4SetQueryBufferLen */
  2173. );
  2174. if (rStatus != WLAN_STATUS_PENDING) {
  2175. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2176. return TDLS_STATUS_RESOURCES;
  2177. }
  2178. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2179. return TDLS_STATUS_SUCCESS;
  2180. }
  2181. /*----------------------------------------------------------------------------*/
  2182. /*! \brief This routine is called to skip scan request.
  2183. *
  2184. * \param[in] prAdapter Pointer to the Adapter structure
  2185. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2186. * \param[in] u4SetBufferLen The length of the set buffer
  2187. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2188. * bytes read from the set buffer. If the call failed due to invalid length of
  2189. * the set buffer, returns the amount of storage needed.
  2190. *
  2191. * \retval TDLS_STATUS_xx
  2192. *
  2193. */
  2194. /*----------------------------------------------------------------------------*/
  2195. static TDLS_STATUS
  2196. TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2197. {
  2198. TDLS_CMD_CORE_T *prCmdContent;
  2199. WLAN_STATUS rStatus;
  2200. /* init command buffer */
  2201. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2202. prCmdContent->u4Command = TDLS_CORE_CMD_TEST_SCAN_SKIP;
  2203. /* send the command */
  2204. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2205. CMD_ID_TDLS_CORE, /* ucCID */
  2206. TRUE, /* fgSetQuery */
  2207. FALSE, /* fgNeedResp */
  2208. FALSE, /* fgIsOid */
  2209. NULL, NULL, /* pfCmdTimeoutHandler */
  2210. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2211. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2212. NULL, /* pvSetQueryBuffer */
  2213. 0 /* u4SetQueryBufferLen */
  2214. );
  2215. if (rStatus != WLAN_STATUS_PENDING) {
  2216. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2217. return TDLS_STATUS_RESOURCES;
  2218. }
  2219. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2220. return TDLS_STATUS_SUCCESS;
  2221. }
  2222. #endif /* TDLS_CFG_CMD_TEST */
  2223. /*----------------------------------------------------------------------------*/
  2224. /*! \brief This routine is called to configure channel switch parameters.
  2225. *
  2226. * \param[in] prAdapter Pointer to the Adapter structure
  2227. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2228. * \param[in] u4SetBufferLen The length of the set buffer
  2229. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2230. * bytes read from the set buffer. If the call failed due to invalid length of
  2231. * the set buffer, returns the amount of storage needed.
  2232. *
  2233. * \retval TDLS_STATUS_xx
  2234. *
  2235. */
  2236. /*----------------------------------------------------------------------------*/
  2237. static TDLS_STATUS
  2238. TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2239. {
  2240. TDLS_CMD_CORE_T *prCmdContent;
  2241. WLAN_STATUS rStatus;
  2242. /* init command buffer */
  2243. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2244. prCmdContent->u4Command = TDLS_CORE_CMD_CHSW_CONF;
  2245. /* send the command */
  2246. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2247. CMD_ID_TDLS_CORE, /* ucCID */
  2248. TRUE, /* fgSetQuery */
  2249. FALSE, /* fgNeedResp */
  2250. FALSE, /* fgIsOid */
  2251. NULL, NULL, /* pfCmdTimeoutHandler */
  2252. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2253. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2254. NULL, /* pvSetQueryBuffer */
  2255. 0 /* u4SetQueryBufferLen */
  2256. );
  2257. if (rStatus != WLAN_STATUS_PENDING) {
  2258. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2259. return TDLS_STATUS_RESOURCES;
  2260. }
  2261. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2262. return TDLS_STATUS_SUCCESS;
  2263. }
  2264. /*----------------------------------------------------------------------------*/
  2265. /*! \brief This routine is called to update channel switch parameters.
  2266. *
  2267. * \param[in] prGlueInfo Pointer to the Adapter structure
  2268. * \param[in] prInBuf A pointer to the command string buffer
  2269. * \param[in] u4InBufLen The length of the buffer
  2270. * \param[out] None
  2271. *
  2272. * \retval None
  2273. *
  2274. * EX: iwpriv wlan0 set_str_cmd 0_9_[TDLS Peer MAC]_
  2275. [NetworkTypeIndex]_[1 (Enable) or (0) Disable]_[1 (Start) or 0 (Stop)]_
  2276. [RegClass]_[Chan]_[SecChanOff]_[1 (Reqular) or (0) One Shot]
  2277. RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
  2278. Secondary Channel Offset: 0 (SCN - no secondary channel)
  2279. 1 (SCA - secondary channel above)
  2280. 2 (SCB - secondary channel below)
  2281. SwitchTime: units of microseconds
  2282. iwpriv wlan0 set_str_cmd 0_9_00:11:22:33:44:01_0_1_0_0_1_0_0
  2283. */
  2284. /*----------------------------------------------------------------------------*/
  2285. static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2286. {
  2287. WLAN_STATUS rStatus;
  2288. TDLS_CMD_CORE_T rCmd;
  2289. UINT_32 u4BufLen;
  2290. /* parse arguments */
  2291. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  2292. rCmd.Content.rCmdChSwConf.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2293. rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2294. rCmd.Content.rCmdChSwConf.fgIsChSwStarted = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2295. rCmd.Content.rCmdChSwConf.ucRegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2296. rCmd.Content.rCmdChSwConf.ucTargetChan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2297. rCmd.Content.rCmdChSwConf.ucSecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2298. rCmd.Content.rCmdChSwConf.fgIsChSwRegular = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2299. DBGLOG(TDLS, INFO, "%s: %pM ucNetTypeIndex=%d, fgIsChSwEnabled=%d, fgIsChSwStarted=%d",
  2300. __func__, (rCmd.aucPeerMac),
  2301. rCmd.Content.rCmdChSwConf.ucNetTypeIndex,
  2302. rCmd.Content.rCmdChSwConf.fgIsChSwEnabled,
  2303. rCmd.Content.rCmdChSwConf.fgIsChSwStarted);
  2304. DBGLOG(TDLS, INFO, " RegClass=%d, TargetChan=%d, SecChanOff=%d, Regular=%d\n",
  2305. rCmd.Content.rCmdChSwConf.ucRegClass,
  2306. rCmd.Content.rCmdChSwConf.ucTargetChan,
  2307. rCmd.Content.rCmdChSwConf.ucSecChanOff, rCmd.Content.rCmdChSwConf.fgIsChSwRegular);
  2308. /* command to do this */
  2309. rStatus = kalIoctl(prGlueInfo, TdlsChSwConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2310. if (rStatus != WLAN_STATUS_SUCCESS) {
  2311. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2312. return;
  2313. }
  2314. }
  2315. /*----------------------------------------------------------------------------*/
  2316. /*! \brief This routine is called to display TDLS related information.
  2317. *
  2318. * \param[in] prGlueInfo Pointer to the Adapter structure
  2319. * \param[in] prInBuf A pointer to the command string buffer
  2320. * \param[in] u4InBufLen The length of the buffer
  2321. * \param[out] None
  2322. *
  2323. * \retval None
  2324. *
  2325. * EX: iwpriv wlan0 set_str_cmd 0_18_[Peer MAC]_[Network Interface ID]_[IsClear]
  2326. Network Interface ID: reference to ENUM_NETWORK_TYPE_INDEX_T
  2327. typedef enum _ENUM_NETWORK_TYPE_INDEX_T {
  2328. NETWORK_TYPE_AIS_INDEX = 0,
  2329. NETWORK_TYPE_P2P_INDEX,
  2330. NETWORK_TYPE_BOW_INDEX,
  2331. NETWORK_TYPE_INDEX_NUM
  2332. } ENUM_NETWORK_TYPE_INDEX_T;
  2333. iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0
  2334. */
  2335. /*----------------------------------------------------------------------------*/
  2336. static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2337. {
  2338. WLAN_STATUS rStatus;
  2339. TDLS_CMD_CORE_T rCmd;
  2340. UINT_32 u4BufLen;
  2341. /* parse arguments */
  2342. kalMemZero(&rCmd, sizeof(rCmd));
  2343. CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
  2344. rCmd.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2345. rCmd.Content.rCmdInfoDisplay.fgIsToClearAllHistory = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2346. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: Command PeerMac=%pM in BSS%u\n",
  2347. __func__, (rCmd.aucPeerMac), rCmd.ucNetTypeIndex);
  2348. /* command to do this */
  2349. rStatus = kalIoctl(prGlueInfo, TdlsInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2350. if (rStatus != WLAN_STATUS_SUCCESS) {
  2351. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2352. return;
  2353. }
  2354. }
  2355. /*----------------------------------------------------------------------------*/
  2356. /*! \brief This routine is called to display key related information.
  2357. *
  2358. * \param[in] prGlueInfo Pointer to the Adapter structure
  2359. * \param[in] prInBuf A pointer to the command string buffer
  2360. * \param[in] u4InBufLen The length of the buffer
  2361. * \param[out] None
  2362. *
  2363. * \retval None
  2364. *
  2365. * EX: iwpriv wlan0 set_str_cmd 0_20
  2366. iwpriv wlan0 set_str_cmd 0_20
  2367. */
  2368. /*----------------------------------------------------------------------------*/
  2369. static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2370. {
  2371. WLAN_STATUS rStatus;
  2372. TDLS_CMD_CORE_T rCmd;
  2373. UINT_32 u4BufLen;
  2374. /* parse arguments */
  2375. kalMemZero(&rCmd, sizeof(rCmd));
  2376. DBGLOG(TDLS, INFO, "<tdls_cmd> %s\n", __func__);
  2377. /* command to do this */
  2378. rStatus = kalIoctl(prGlueInfo, TdlsKeyInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2379. if (rStatus != WLAN_STATUS_SUCCESS) {
  2380. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2381. return;
  2382. }
  2383. }
  2384. /*----------------------------------------------------------------------------*/
  2385. /*! \brief This routine is called to update MIB parameters.
  2386. *
  2387. * \param[in] prGlueInfo Pointer to the Adapter structure
  2388. * \param[in] prInBuf A pointer to the command string buffer
  2389. * \param[in] u4InBufLen The length of the buffer
  2390. * \param[out] None
  2391. *
  2392. * \retval None
  2393. *
  2394. * EX: iwpriv wlan0 set_str_cmd 0_6_[TdlsEn]_[UapsdEn]_[PsmEn]_[PtiWin]_[CWCap]_
  2395. [AckMisRetry]_[RspTimeout]_[CWPbDelay]_[DRWin]_[LowestAcInt]
  2396. iwpriv wlan0 set_str_cmd 0_6_1_1_0_1_1_3_5_1000_2_1
  2397. reference to TDLS_CMD_CORE_MIB_PARAM_UPDATE_T
  2398. */
  2399. /*----------------------------------------------------------------------------*/
  2400. static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2401. {
  2402. WLAN_STATUS rStatus;
  2403. TDLS_CMD_CORE_T rCmd;
  2404. UINT_32 u4BufLen;
  2405. /* reset */
  2406. kalMemZero(&rCmd, sizeof(rCmd));
  2407. /* parse arguments */
  2408. rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented =
  2409. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2410. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated =
  2411. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2412. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2413. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow =
  2414. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2415. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated =
  2416. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2417. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit =
  2418. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2419. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2420. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2421. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow =
  2422. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2423. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval =
  2424. CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2425. DBGLOG(TDLS, INFO, "<tdls_cmd> MIB param = %d %d %d %d %d %d %d %d %d %d\n",
  2426. rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented,
  2427. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated,
  2428. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated,
  2429. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow,
  2430. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated,
  2431. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit,
  2432. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout,
  2433. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay,
  2434. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow,
  2435. rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval);
  2436. /* command to do this */
  2437. rStatus = kalIoctl(prGlueInfo, TdlsMibParamUpdate, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2438. if (rStatus != WLAN_STATUS_SUCCESS) {
  2439. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2440. return;
  2441. }
  2442. }
  2443. /*----------------------------------------------------------------------------*/
  2444. /*! \brief This routine is called to update setup parameters.
  2445. *
  2446. * \param[in] prGlueInfo Pointer to the Adapter structure
  2447. * \param[in] prInBuf A pointer to the command string buffer
  2448. * \param[in] u4InBufLen The length of the buffer
  2449. * \param[out] None
  2450. *
  2451. * \retval None
  2452. *
  2453. * EX: iwpriv wlan0 set_str_cmd 0_17_[20/40 Support]
  2454. iwpriv wlan0 set_str_cmd 0_17_1
  2455. */
  2456. /*----------------------------------------------------------------------------*/
  2457. static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2458. {
  2459. WLAN_STATUS rStatus;
  2460. TDLS_CMD_CORE_T rCmd;
  2461. UINT_32 u4BufLen;
  2462. /* parse arguments */
  2463. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  2464. rCmd.Content.rCmdSetupConf.fgIs2040Supported = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2465. DBGLOG(TDLS, INFO, "%s: rCmdSetupConf=%d\n", __func__, rCmd.Content.rCmdSetupConf.fgIs2040Supported);
  2466. /* command to do this */
  2467. prGlueInfo->rTdlsLink.fgIs2040Sup = rCmd.Content.rCmdSetupConf.fgIs2040Supported;
  2468. rStatus = kalIoctl(prGlueInfo, TdlsSetupConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2469. if (rStatus != WLAN_STATUS_SUCCESS) {
  2470. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2471. return;
  2472. }
  2473. }
  2474. /*----------------------------------------------------------------------------*/
  2475. /*! \brief This routine is called to update UAPSD parameters.
  2476. *
  2477. * \param[in] prGlueInfo Pointer to the Adapter structure
  2478. * \param[in] prInBuf A pointer to the command string buffer
  2479. * \param[in] u4InBufLen The length of the buffer
  2480. * \param[out] None
  2481. *
  2482. * \retval None
  2483. *
  2484. * EX: iwpriv wlan0 set_str_cmd 0_8_[SP timeout skip]_[PTI timeout skip]
  2485. iwpriv wlan0 set_str_cmd 0_8_1_1
  2486. */
  2487. /*----------------------------------------------------------------------------*/
  2488. static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  2489. {
  2490. WLAN_STATUS rStatus;
  2491. TDLS_CMD_CORE_T rCmd;
  2492. UINT_32 u4BufLen;
  2493. /* parse arguments */
  2494. kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
  2495. /* UAPSD Service Period */
  2496. rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2497. rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  2498. /* PTI Service Period */
  2499. fgIsPtiTimeoutSkip = rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip;
  2500. DBGLOG(TDLS, INFO, "%s: fgIsSpTimeoutSkip=%d, fgIsPtiTimeoutSkip=%d\n",
  2501. __func__, rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip, fgIsPtiTimeoutSkip);
  2502. /* command to do this */
  2503. rStatus = kalIoctl(prGlueInfo, TdlsUapsdConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  2504. if (rStatus != WLAN_STATUS_SUCCESS) {
  2505. DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus);
  2506. return;
  2507. }
  2508. }
  2509. /*----------------------------------------------------------------------------*/
  2510. /*! \brief This routine is called to display TDLS all information.
  2511. *
  2512. * \param[in] prAdapter Pointer to the Adapter structure
  2513. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2514. * \param[in] u4SetBufferLen The length of the set buffer
  2515. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2516. * bytes read from the set buffer. If the call failed due to invalid length of
  2517. * the set buffer, returns the amount of storage needed.
  2518. *
  2519. * \retval TDLS_STATUS_xx
  2520. *
  2521. * iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0
  2522. *
  2523. */
  2524. /*----------------------------------------------------------------------------*/
  2525. static TDLS_STATUS
  2526. TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2527. {
  2528. GLUE_INFO_T *prGlueInfo;
  2529. TDLS_CMD_CORE_T *prCmdContent;
  2530. STA_RECORD_T *prStaRec;
  2531. TDLS_INFO_LINK_T *prLink;
  2532. UINT32 u4StartIdx;
  2533. UINT32 u4PeerNum;
  2534. BOOLEAN fgIsListAll;
  2535. UINT8 ucMacZero[6];
  2536. UINT32 u4HisIdx;
  2537. UINT8 ucNetTypeIndex;
  2538. /* init */
  2539. prGlueInfo = prAdapter->prGlueInfo;
  2540. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2541. u4StartIdx = 0;
  2542. u4PeerNum = 1;
  2543. fgIsListAll = TRUE;
  2544. kalMemZero(ucMacZero, sizeof(ucMacZero));
  2545. ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
  2546. /* display common information */
  2547. DBGLOG(TDLS, TRACE, "TDLS common:\n");
  2548. DBGLOG(TDLS, TRACE, "\t\trFreeSwRfbList=%u\n", (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem);
  2549. DBGLOG(TDLS, TRACE, "\t\tjiffies=%u %ums (HZ=%d)\n", (UINT32) jiffies, (UINT32) kalGetTimeTick(), HZ);
  2550. /* display disconnection history information */
  2551. DBGLOG(TDLS, TRACE, "TDLS link history: %d\n", prGlueInfo->rTdlsLink.u4LinkIdx);
  2552. for (u4HisIdx = prGlueInfo->rTdlsLink.u4LinkIdx + 1; u4HisIdx < TDLS_LINK_HISTORY_MAX; u4HisIdx++) {
  2553. prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx];
  2554. if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0)
  2555. continue; /* skip all zero */
  2556. DBGLOG(TDLS, TRACE,
  2557. "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n",
  2558. u4HisIdx, prLink->aucPeerMac,
  2559. prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start),
  2560. prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end),
  2561. prLink->ucReasonCode,
  2562. prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP));
  2563. if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) {
  2564. DBGLOG(TDLS, TRACE,
  2565. "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n",
  2566. prLink->ucHtBa[0], prLink->ucHtBa[1],
  2567. prLink->ucHtBa[2], prLink->ucHtBa[3],
  2568. prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]);
  2569. }
  2570. }
  2571. for (u4HisIdx = 0; u4HisIdx <= prGlueInfo->rTdlsLink.u4LinkIdx; u4HisIdx++) {
  2572. prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx];
  2573. if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0)
  2574. continue; /* skip all zero, use continue, not break */
  2575. DBGLOG(TDLS, TRACE,
  2576. "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n",
  2577. u4HisIdx, (prLink->aucPeerMac),
  2578. prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start),
  2579. prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end),
  2580. prLink->ucReasonCode,
  2581. prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP));
  2582. if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) {
  2583. DBGLOG(TDLS, TRACE,
  2584. "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n",
  2585. prLink->ucHtBa[0], prLink->ucHtBa[1],
  2586. prLink->ucHtBa[2], prLink->ucHtBa[3],
  2587. prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]);
  2588. }
  2589. }
  2590. DBGLOG(TDLS, TRACE, "\n");
  2591. /* display link information */
  2592. if (prCmdContent != NULL) {
  2593. if (kalMemCmp(prCmdContent->aucPeerMac, ucMacZero, 6) != 0) {
  2594. prStaRec = cnmGetStaRecByAddress(prAdapter,
  2595. prCmdContent->ucNetTypeIndex, prCmdContent->aucPeerMac);
  2596. if (prStaRec == NULL)
  2597. fgIsListAll = TRUE;
  2598. }
  2599. ucNetTypeIndex = prCmdContent->ucNetTypeIndex;
  2600. }
  2601. while (1) {
  2602. if (fgIsListAll == TRUE) {
  2603. /* list all TDLS peers */
  2604. prStaRec = cnmStaTheTypeGet(prAdapter, ucNetTypeIndex, STA_TYPE_TDLS_PEER, &u4StartIdx);
  2605. if (prStaRec == NULL)
  2606. break;
  2607. }
  2608. DBGLOG(TDLS, TRACE, "-------- TDLS %d: 0x %pM\n", u4PeerNum, (prStaRec->aucMacAddr));
  2609. DBGLOG(TDLS, TRACE, "\t\t\t State %d, PM %d, Cap 0x%x\n",
  2610. prStaRec->ucStaState, prStaRec->fgIsInPS, prStaRec->u2CapInfo);
  2611. DBGLOG(TDLS, TRACE, "\t\t\t SetupDisable %d, ChSwDisable %d\n",
  2612. prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited);
  2613. if (fgIsListAll == FALSE)
  2614. break; /* only list one */
  2615. }
  2616. /* check if we need to clear all histories */
  2617. if ((prCmdContent != NULL) && (prCmdContent->Content.rCmdInfoDisplay.fgIsToClearAllHistory == TRUE)) {
  2618. kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink));
  2619. prGlueInfo->rTdlsLink.u4LinkIdx = TDLS_LINK_HISTORY_MAX - 1;
  2620. }
  2621. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2622. return TDLS_STATUS_SUCCESS;
  2623. }
  2624. /*----------------------------------------------------------------------------*/
  2625. /*! \brief This routine is called to display key information.
  2626. *
  2627. * \param[in] prAdapter Pointer to the Adapter structure
  2628. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2629. * \param[in] u4SetBufferLen The length of the set buffer
  2630. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2631. * bytes read from the set buffer. If the call failed due to invalid length of
  2632. * the set buffer, returns the amount of storage needed.
  2633. *
  2634. * \retval TDLS_STATUS_xx
  2635. *
  2636. */
  2637. /*----------------------------------------------------------------------------*/
  2638. static TDLS_STATUS
  2639. TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2640. {
  2641. TDLS_CMD_CORE_T *prCmdContent;
  2642. WLAN_STATUS rStatus;
  2643. /* init command buffer */
  2644. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2645. prCmdContent->u4Command = TDLS_CORE_CMD_KEY_INFO;
  2646. /* send the command */
  2647. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2648. CMD_ID_TDLS_CORE, /* ucCID */
  2649. TRUE, /* fgSetQuery */
  2650. FALSE, /* fgNeedResp */
  2651. FALSE, /* fgIsOid */
  2652. NULL, NULL, /* pfCmdTimeoutHandler */
  2653. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2654. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2655. NULL, /* pvSetQueryBuffer */
  2656. 0 /* u4SetQueryBufferLen */
  2657. );
  2658. if (rStatus != WLAN_STATUS_PENDING) {
  2659. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2660. return TDLS_STATUS_RESOURCES;
  2661. }
  2662. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2663. return TDLS_STATUS_SUCCESS;
  2664. }
  2665. /*----------------------------------------------------------------------------*/
  2666. /*! \brief This routine is called to record a disconnection event.
  2667. *
  2668. * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
  2669. * \param[in] fgIsTearDown TRUE: the link is torn down
  2670. * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
  2671. * \param[in] fgIsFromUs TRUE: tear down is from us
  2672. * \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE)
  2673. *
  2674. * \retval none
  2675. */
  2676. /*----------------------------------------------------------------------------*/
  2677. static VOID
  2678. TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo,
  2679. BOOLEAN fgIsTearDown,
  2680. UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers)
  2681. {
  2682. TDLS_INFO_LINK_T *prLink;
  2683. DBGLOG(TDLS, INFO,
  2684. "<tdls_evt> %s: record history for %pM %d %d %d %d\n",
  2685. __func__, pucPeerMac, prGlueInfo->rTdlsLink.u4LinkIdx,
  2686. fgIsTearDown, fgIsFromUs, u2ReasonCode);
  2687. /* check duplicate one */
  2688. if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) {
  2689. DBGLOG(TDLS, ERROR, "<tdls_evt> %s: u4LinkIdx >= TDLS_LINK_HISTORY_MAX\n", __func__);
  2690. /* reset to 0 */
  2691. prGlueInfo->rTdlsLink.u4LinkIdx = 0;
  2692. }
  2693. prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx];
  2694. if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) == 0) {
  2695. if ((prLink->ucReasonCode == u2ReasonCode) && (prLink->fgIsFromUs == fgIsFromUs)) {
  2696. /* same Peer MAC, Reason Code, Trigger source */
  2697. if (fgIsTearDown == TRUE) {
  2698. if (prLink->jiffies_end != 0) {
  2699. /* already torn down */
  2700. prLink->ucDupCount++;
  2701. return;
  2702. }
  2703. } else {
  2704. /* already built */
  2705. prLink->ucDupCount++;
  2706. return;
  2707. }
  2708. }
  2709. }
  2710. /* search old entry */
  2711. if (fgIsTearDown == TRUE) {
  2712. /* TODO: need to search all entries to find it if we support multiple TDLS link design */
  2713. if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) {
  2714. /* error! can not find the link entry */
  2715. DBGLOG(TDLS, INFO, "<tdls_evt> %s: cannot find the same entry!!!\n", __func__);
  2716. return;
  2717. }
  2718. prLink->jiffies_end = jiffies;
  2719. prLink->ucReasonCode = (UINT8) u2ReasonCode;
  2720. prLink->fgIsFromUs = fgIsFromUs;
  2721. } else {
  2722. /* record new one */
  2723. prGlueInfo->rTdlsLink.u4LinkIdx++;
  2724. if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX)
  2725. prGlueInfo->rTdlsLink.u4LinkIdx = 0;
  2726. prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx];
  2727. prLink->jiffies_start = jiffies;
  2728. prLink->jiffies_end = 0;
  2729. kalMemCopy(&prLink->aucPeerMac, pucPeerMac, 6);
  2730. prLink->ucReasonCode = 0;
  2731. prLink->fgIsFromUs = (UINT8) fgIsFromUs;
  2732. prLink->ucDupCount = 0;
  2733. if (prOthers != NULL) {
  2734. /* record other parameters */
  2735. TDLS_LINK_HIS_OTHERS_T *prHisOthers;
  2736. prHisOthers = (TDLS_LINK_HIS_OTHERS_T *) prOthers;
  2737. if (prHisOthers->fgIsHt == TRUE)
  2738. prLink->ucHtCap |= TDLS_INFO_LINK_HT_CAP_SUP;
  2739. }
  2740. }
  2741. }
  2742. /*----------------------------------------------------------------------------*/
  2743. /*! \brief This routine is called to update a disconnection event.
  2744. *
  2745. * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
  2746. * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
  2747. * \param[in] eFmeStatus TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME
  2748. * \param[in] pInfo other information
  2749. *
  2750. * \retval none
  2751. */
  2752. /*----------------------------------------------------------------------------*/
  2753. static VOID
  2754. TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo,
  2755. UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo)
  2756. {
  2757. TDLS_INFO_LINK_T *prLink;
  2758. UINT32 u4LinkIdx;
  2759. UINT32 u4Tid;
  2760. /* sanity check */
  2761. if ((eFmeStatus < TDLS_HOST_EVENT_SF_BA) || (eFmeStatus > TDLS_HOST_EVENT_SF_BA_RSP_DECLINE)) {
  2762. /* do not care these frames */
  2763. return;
  2764. }
  2765. DBGLOG(TDLS, INFO,
  2766. "<tdls_evt> %s: update history for %pM %d %d\n",
  2767. __func__, (pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx, eFmeStatus);
  2768. /* init */
  2769. u4LinkIdx = prGlueInfo->rTdlsLink.u4LinkIdx;
  2770. prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4LinkIdx];
  2771. /* TODO: need to search all entries to find it if we support multiple TDLS link design */
  2772. if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) {
  2773. /* error! can not find the link entry */
  2774. DBGLOG(TDLS, INFO, "<tdls_evt> %s: cannot find the same entry!!!\n", __func__);
  2775. return;
  2776. }
  2777. /* update */
  2778. u4Tid = *(UINT32 *) pInfo;
  2779. switch (eFmeStatus) {
  2780. case TDLS_HOST_EVENT_SF_BA:
  2781. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP;
  2782. break;
  2783. case TDLS_HOST_EVENT_SF_BA_OK:
  2784. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_OK;
  2785. break;
  2786. case TDLS_HOST_EVENT_SF_BA_DECLINE:
  2787. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_DECLINE;
  2788. break;
  2789. case TDLS_HOST_EVENT_SF_BA_PEER:
  2790. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_PEER;
  2791. break;
  2792. case TDLS_HOST_EVENT_SF_BA_RSP_OK:
  2793. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_OK;
  2794. break;
  2795. case TDLS_HOST_EVENT_SF_BA_RSP_DECLINE:
  2796. prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_DECLINE;
  2797. break;
  2798. }
  2799. /* display TDLS link history */
  2800. TdlsInfoDisplay(prGlueInfo->prAdapter, NULL, 0, NULL);
  2801. }
  2802. /*----------------------------------------------------------------------------*/
  2803. /*! \brief This routine is called to configure TDLS MIB parameters.
  2804. *
  2805. * \param[in] prAdapter Pointer to the Adapter structure
  2806. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2807. * \param[in] u4SetBufferLen The length of the set buffer
  2808. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2809. * bytes read from the set buffer. If the call failed due to invalid length of
  2810. * the set buffer, returns the amount of storage needed.
  2811. *
  2812. * \retval TDLS_STATUS_xx
  2813. *
  2814. */
  2815. /*----------------------------------------------------------------------------*/
  2816. static TDLS_STATUS
  2817. TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2818. {
  2819. TDLS_CMD_CORE_T *prCmdContent;
  2820. WLAN_STATUS rStatus;
  2821. /* init command buffer */
  2822. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2823. prCmdContent->u4Command = TDLS_CORE_CMD_MIB_UPDATE;
  2824. /* send the command */
  2825. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2826. CMD_ID_TDLS_CORE, /* ucCID */
  2827. TRUE, /* fgSetQuery */
  2828. FALSE, /* fgNeedResp */
  2829. FALSE, /* fgIsOid */
  2830. NULL, NULL, /* pfCmdTimeoutHandler */
  2831. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2832. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2833. NULL, /* pvSetQueryBuffer */
  2834. 0 /* u4SetQueryBufferLen */
  2835. );
  2836. if (rStatus != WLAN_STATUS_PENDING) {
  2837. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2838. return TDLS_STATUS_RESOURCES;
  2839. }
  2840. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2841. return TDLS_STATUS_SUCCESS;
  2842. }
  2843. /*----------------------------------------------------------------------------*/
  2844. /*! \brief This routine is called to configure TDLS SETUP parameters.
  2845. *
  2846. * \param[in] prAdapter Pointer to the Adapter structure
  2847. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2848. * \param[in] u4SetBufferLen The length of the set buffer
  2849. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2850. * bytes read from the set buffer. If the call failed due to invalid length of
  2851. * the set buffer, returns the amount of storage needed.
  2852. *
  2853. * \retval TDLS_STATUS_xx
  2854. *
  2855. */
  2856. /*----------------------------------------------------------------------------*/
  2857. static TDLS_STATUS
  2858. TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2859. {
  2860. TDLS_CMD_CORE_T *prCmdContent;
  2861. WLAN_STATUS rStatus;
  2862. /* init command buffer */
  2863. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2864. prCmdContent->u4Command = TDLS_CORE_CMD_SETUP_CONF;
  2865. /* send the command */
  2866. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2867. CMD_ID_TDLS_CORE, /* ucCID */
  2868. TRUE, /* fgSetQuery */
  2869. FALSE, /* fgNeedResp */
  2870. FALSE, /* fgIsOid */
  2871. NULL, NULL, /* pfCmdTimeoutHandler */
  2872. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2873. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2874. NULL, /* pvSetQueryBuffer */
  2875. 0 /* u4SetQueryBufferLen */
  2876. );
  2877. if (rStatus != WLAN_STATUS_PENDING) {
  2878. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2879. return TDLS_STATUS_RESOURCES;
  2880. }
  2881. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2882. return TDLS_STATUS_SUCCESS;
  2883. }
  2884. /*----------------------------------------------------------------------------*/
  2885. /*! \brief This routine is called to configure UAPSD parameters.
  2886. *
  2887. * \param[in] prAdapter Pointer to the Adapter structure
  2888. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  2889. * \param[in] u4SetBufferLen The length of the set buffer
  2890. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  2891. * bytes read from the set buffer. If the call failed due to invalid length of
  2892. * the set buffer, returns the amount of storage needed.
  2893. *
  2894. * \retval TDLS_STATUS_xx
  2895. *
  2896. */
  2897. /*----------------------------------------------------------------------------*/
  2898. static TDLS_STATUS
  2899. TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  2900. {
  2901. TDLS_CMD_CORE_T *prCmdContent;
  2902. WLAN_STATUS rStatus;
  2903. /* init command buffer */
  2904. prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer;
  2905. prCmdContent->u4Command = TDLS_CORE_CMD_UAPSD_CONF;
  2906. /* send the command */
  2907. rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
  2908. CMD_ID_TDLS_CORE, /* ucCID */
  2909. TRUE, /* fgSetQuery */
  2910. FALSE, /* fgNeedResp */
  2911. FALSE, /* fgIsOid */
  2912. NULL, NULL, /* pfCmdTimeoutHandler */
  2913. sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
  2914. (PUINT_8) prCmdContent, /* pucInfoBuffer */
  2915. NULL, /* pvSetQueryBuffer */
  2916. 0 /* u4SetQueryBufferLen */
  2917. );
  2918. if (rStatus != WLAN_STATUS_PENDING) {
  2919. DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__);
  2920. return TDLS_STATUS_RESOURCES;
  2921. }
  2922. DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__);
  2923. return TDLS_STATUS_SUCCESS;
  2924. }
  2925. /*----------------------------------------------------------------------------*/
  2926. /*! \brief This routine is called to update frame status.
  2927. *
  2928. * \param[in] prGlueInfo Pointer to the Adapter structure
  2929. * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
  2930. * \param[in] u4InBufLen The length of the buffer
  2931. * \param[out] None
  2932. *
  2933. * \retval None
  2934. *
  2935. */
  2936. /*----------------------------------------------------------------------------*/
  2937. static void TdlsEventFmeStatus(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen)
  2938. {
  2939. TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus;
  2940. STA_RECORD_T *prStaRec;
  2941. UINT32 u4Tid;
  2942. /* init */
  2943. u4Tid = *(UINT32 *) prInBuf;
  2944. prInBuf += 4; /* skip u4EventSubId */
  2945. /* sanity check */
  2946. prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf);
  2947. if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec)))
  2948. return;
  2949. prInBuf++;
  2950. /* update status */
  2951. eFmeStatus = *prInBuf;
  2952. TdlsLinkHistoryRecordUpdate(prGlueInfo, prStaRec->aucMacAddr, eFmeStatus, &u4Tid);
  2953. }
  2954. /*----------------------------------------------------------------------------*/
  2955. /*! \brief This routine is called to collect TDLS statistics from firmware.
  2956. *
  2957. * \param[in] prGlueInfo Pointer to the Adapter structure
  2958. * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
  2959. * \param[in] u4InBufLen The length of the buffer
  2960. * \param[out] None
  2961. *
  2962. * \retval None
  2963. *
  2964. */
  2965. /*----------------------------------------------------------------------------*/
  2966. static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen)
  2967. {
  2968. STA_RECORD_T *prStaRec;
  2969. STAT_CNT_INFO_FW_T *prStat;
  2970. UINT32 u4RateId;
  2971. /* init */
  2972. prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf);
  2973. if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec)))
  2974. return;
  2975. prInBuf += 4; /* skip prStaRec->ucIndex */
  2976. /* update statistics */
  2977. kalMemCopy(&prStaRec->rTdlsStatistics.rFw, prInBuf, sizeof(prStaRec->rTdlsStatistics.rFw));
  2978. /* display statistics */
  2979. prStat = &prStaRec->rTdlsStatistics.rFw;
  2980. DBGLOG(TDLS, TRACE, "<tdls_evt> peer [%pM] statistics:\n", (prStaRec->aucMacAddr));
  2981. DBGLOG(TDLS, TRACE, "\t\tT%d %d %d (P%d %d) (%dus) - E%d 0x%x - R%d (P%d)\n",
  2982. prStat->u4NumOfTx, prStat->u4NumOfTxOK, prStat->u4NumOfTxRetry,
  2983. prStat->u4NumOfPtiRspTxOk, prStat->u4NumOfPtiRspTxErr,
  2984. prStat->u4TxDoneAirTimeMax,
  2985. prStat->u4NumOfTxErr, prStat->u4TxErrBitmap, prStat->u4NumOfRx, prStat->u4NumOfPtiRspRx);
  2986. DBGLOG(TDLS, TRACE, "\t\t");
  2987. for (u4RateId = prStat->u4TxRateOkHisId; u4RateId < STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM; u4RateId++)
  2988. DBGLOG(TDLS, TRACE,
  2989. "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]);
  2990. for (u4RateId = 0; u4RateId < prStat->u4TxRateOkHisId; u4RateId++)
  2991. DBGLOG(TDLS, TRACE,
  2992. "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]);
  2993. DBGLOG(TDLS, TRACE, "\n\n");
  2994. }
  2995. /*----------------------------------------------------------------------------*/
  2996. /*! \brief This routine is called to do tear down.
  2997. *
  2998. * \param[in] prGlueInfo Pointer to the Adapter structure
  2999. * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
  3000. * \param[in] u4InBufLen The length of the buffer
  3001. * \param[out] None
  3002. *
  3003. * \retval None
  3004. *
  3005. */
  3006. /*----------------------------------------------------------------------------*/
  3007. static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen)
  3008. {
  3009. STA_RECORD_T *prStaRec;
  3010. UINT16 u2ReasonCode;
  3011. UINT32 u4TearDownSubId;
  3012. UINT8 *pMac, aucZeroMac[6];
  3013. /* init */
  3014. u4TearDownSubId = *(UINT32 *) prInBuf;
  3015. kalMemZero(aucZeroMac, sizeof(aucZeroMac));
  3016. pMac = aucZeroMac;
  3017. prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4));
  3018. if (prStaRec != NULL)
  3019. pMac = prStaRec->aucMacAddr;
  3020. /* handle */
  3021. if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) {
  3022. DBGLOG(TDLS, WARN, "<tdls_evt> %s: peer [%pM] Reason=PTI timeout\n",
  3023. __func__, pMac);
  3024. } else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) {
  3025. DBGLOG(TDLS, WARN, "<tdls_evt> %s: peer [%pM] Reason=AGE timeout\n",
  3026. __func__, pMac);
  3027. } else {
  3028. DBGLOG(TDLS, WARN, "<tdls_evt> %s: peer [%pM] Reason=%d\n",
  3029. __func__, pMac, u4TearDownSubId);
  3030. }
  3031. /* sanity check */
  3032. if (prStaRec == NULL)
  3033. return;
  3034. if (fgIsPtiTimeoutSkip == TRUE) {
  3035. /* skip PTI timeout event */
  3036. if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) {
  3037. DBGLOG(TDLS, WARN, "<tdls_evt> %s: skip PTI timeout\n", __func__);
  3038. return;
  3039. }
  3040. }
  3041. /* record history */
  3042. if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT)
  3043. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT;
  3044. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT)
  3045. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT;
  3046. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_FAIL)
  3047. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL;
  3048. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL)
  3049. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL;
  3050. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX)
  3051. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX;
  3052. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_NON_STATE3)
  3053. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3;
  3054. else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN)
  3055. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN;
  3056. else {
  3057. /* shall not be here */
  3058. u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN;
  3059. }
  3060. TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, TRUE, u2ReasonCode, NULL);
  3061. /* correct correct reason code for PTI or AGE timeout to supplicant */
  3062. if ((u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT) ||
  3063. (u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT)) {
  3064. u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE;
  3065. }
  3066. /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
  3067. cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
  3068. prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, u2ReasonCode, GFP_ATOMIC);
  3069. }
  3070. /*----------------------------------------------------------------------------*/
  3071. /*! \brief This routine is called to do tx down.
  3072. *
  3073. * \param[in] prGlueInfo Pointer to the Adapter structure
  3074. * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
  3075. * \param[in] u4InBufLen The length of the buffer
  3076. * \param[out] None
  3077. *
  3078. * \retval None
  3079. *
  3080. */
  3081. /*----------------------------------------------------------------------------*/
  3082. static void TdlsEventTxDone(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen)
  3083. {
  3084. /* UINT32 u4FmeIdx; */
  3085. UINT8 *pucFmeHdr;
  3086. UINT8 ucErrStatus;
  3087. ucErrStatus = *(UINT32 *) prInBuf;
  3088. pucFmeHdr = prInBuf + 4; /* skip ucErrStatus */
  3089. if (ucErrStatus == 0)
  3090. DBGLOG(TDLS, TRACE, "<tdls_evt> %s: OK to tx a TDLS action:", __func__);
  3091. else
  3092. DBGLOG(TDLS, TRACE, "<tdls_evt> %s: fail to tx a TDLS action (err=0x%x):", __func__, ucErrStatus);
  3093. #if 0
  3094. /* dump TX packet content from wlan header */
  3095. for (u4FmeIdx = 0; u4FmeIdx < (u4InBufLen - 4); u4FmeIdx++) {
  3096. if ((u4FmeIdx % 16) == 0)
  3097. DBGLOG(TDLS, TRACE, "\n");
  3098. DBGLOG(TDLS, TRACE, "%02x ", *pucFmeHdr++);
  3099. }
  3100. DBGLOG(TDLS, TRACE, "\n\n");
  3101. #endif
  3102. }
  3103. /*******************************************************************************
  3104. * P U B L I C F U N C T I O N S
  3105. ********************************************************************************
  3106. */
  3107. /*----------------------------------------------------------------------------*/
  3108. /*! \brief This routine is called to parse TDLS Extended Capabilities element.
  3109. *
  3110. * \param[in] prGlueInfo Pointer to the Adapter structure
  3111. * \param[in] prInBuf A pointer to the command string buffer
  3112. * \param[in] u4InBufLen The length of the buffer
  3113. * \param[out] None
  3114. *
  3115. * \retval None
  3116. */
  3117. /*----------------------------------------------------------------------------*/
  3118. VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE)
  3119. {
  3120. UINT_8 *pucIeExtCap;
  3121. /* sanity check */
  3122. if ((prStaRec == NULL) || (pucIE == NULL))
  3123. return;
  3124. if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP)
  3125. return;
  3126. /*
  3127. from bit0 ~
  3128. bit 38: TDLS Prohibited
  3129. The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The
  3130. field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is
  3131. allowed.
  3132. */
  3133. if (IE_LEN(pucIE) < 5)
  3134. return; /* we need 39/8 = 5 bytes */
  3135. /* init */
  3136. prStaRec->fgTdlsIsProhibited = FALSE;
  3137. prStaRec->fgTdlsIsChSwProhibited = FALSE;
  3138. /* parse */
  3139. pucIeExtCap = pucIE + 2;
  3140. pucIeExtCap += 4; /* shift to the byte we care about */
  3141. if ((*pucIeExtCap) & BIT(38 - 32))
  3142. prStaRec->fgTdlsIsProhibited = TRUE;
  3143. if ((*pucIeExtCap) & BIT(39 - 32))
  3144. prStaRec->fgTdlsIsChSwProhibited = TRUE;
  3145. DBGLOG(TDLS, TRACE,
  3146. "<tdls> %s: AP [%pM] tdls prohibit bit=%d %d\n",
  3147. __func__,
  3148. prStaRec->aucMacAddr, prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited);
  3149. }
  3150. /*----------------------------------------------------------------------------*/
  3151. /*!
  3152. * \brief This routine is called to transmit a TDLS data frame from nl80211.
  3153. *
  3154. * \param[in] pvAdapter Pointer to the Adapter structure.
  3155. * \param[in]
  3156. * \param[in]
  3157. * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE
  3158. *
  3159. * \retval WLAN_STATUS_SUCCESS
  3160. * \retval WLAN_STATUS_INVALID_LENGTH
  3161. */
  3162. /*----------------------------------------------------------------------------*/
  3163. int
  3164. TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev,
  3165. const u8 *peer, u8 action_code, u8 dialog_token,
  3166. u16 status_code, u32 peer_capability,
  3167. bool initiator, const u8 *buf, size_t len)
  3168. {
  3169. ADAPTER_T *prAdapter;
  3170. GLUE_INFO_T *prGlueInfo;
  3171. BSS_INFO_T *prAisBssInfo;
  3172. WLAN_STATUS rStatus;
  3173. UINT_32 u4BufLen;
  3174. TDLS_MGMT_TX_INFO *prMgmtTxInfo;
  3175. /*
  3176. Have correct behavior for STAUT receiving TDLS Setup Request after sending TDLS
  3177. Set Request and before receiving TDLS Setup Response:
  3178. -- Source Address of received Request is higher than own MAC address
  3179. -- Source Address of received Request is lower than own MAC address
  3180. ==> STA with larger MAC address will send the response frame.
  3181. Supplicant will do this in wpa_tdls_process_tpk_m1().
  3182. */
  3183. /* sanity check */
  3184. if ((wiphy == NULL) || (peer == NULL)) {
  3185. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: wrong 0x%p 0x%p!\n", __func__, wiphy, peer);
  3186. return -EINVAL;
  3187. }
  3188. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: [%pM] %d %d %d 0x%p %u\n",
  3189. __func__, peer, action_code, dialog_token, status_code, buf, (UINT32) len);
  3190. /* init */
  3191. prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy);
  3192. if (prGlueInfo == NULL) {
  3193. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo);
  3194. return -EINVAL;
  3195. }
  3196. prAdapter = prGlueInfo->prAdapter;
  3197. if (prAdapter->fgTdlsIsSup == FALSE) {
  3198. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: firmware TDLS is not supported!\n", __func__);
  3199. return -EBUSY;
  3200. }
  3201. prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  3202. if (prAisBssInfo->fgTdlsIsProhibited == TRUE) {
  3203. /* do not send anything if TDLS is prohibited in the BSS */
  3204. return 0;
  3205. }
  3206. prMgmtTxInfo = kalMemAlloc(sizeof(TDLS_MGMT_TX_INFO), VIR_MEM_TYPE);
  3207. if (prMgmtTxInfo == NULL) {
  3208. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: allocate fail!\n", __func__);
  3209. return -ENOMEM;
  3210. }
  3211. kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO));
  3212. if (peer != NULL)
  3213. kalMemCopy(prMgmtTxInfo->aucPeer, peer, 6);
  3214. prMgmtTxInfo->ucActionCode = action_code;
  3215. prMgmtTxInfo->ucDialogToken = dialog_token;
  3216. prMgmtTxInfo->u2StatusCode = status_code;
  3217. if (buf != NULL) {
  3218. if (len > sizeof(prMgmtTxInfo->aucSecBuf)) {
  3219. kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
  3220. return -EINVAL;
  3221. }
  3222. prMgmtTxInfo->u4SecBufLen = len;
  3223. kalMemCopy(prMgmtTxInfo->aucSecBuf, buf, len);
  3224. }
  3225. /* send the TDLS action data frame */
  3226. rStatus = kalIoctl(prGlueInfo,
  3227. TdlsexMgmtCtrl,
  3228. prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  3229. /*
  3230. clear all content to avoid any bug if we dont yet execute TdlsexMgmtCtrl()
  3231. then kalIoctl finishes
  3232. */
  3233. kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO));
  3234. if (rStatus != WLAN_STATUS_SUCCESS) {
  3235. DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus);
  3236. kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
  3237. return -EINVAL;
  3238. }
  3239. kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
  3240. return 0;
  3241. }
  3242. /*----------------------------------------------------------------------------*/
  3243. /*!
  3244. * \brief This routine is called to enable or disable TDLS link from upper layer.
  3245. *
  3246. * \param[in] pvAdapter Pointer to the Adapter structure.
  3247. * \param[in]
  3248. * \param[in]
  3249. * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE
  3250. *
  3251. * \retval WLAN_STATUS_SUCCESS
  3252. * \retval WLAN_STATUS_INVALID_LENGTH
  3253. */
  3254. /*----------------------------------------------------------------------------*/
  3255. int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev,
  3256. const u8 *peer, enum nl80211_tdls_operation oper)
  3257. {
  3258. ADAPTER_T *prAdapter;
  3259. GLUE_INFO_T *prGlueInfo;
  3260. WLAN_STATUS rStatus;
  3261. UINT_32 u4BufLen;
  3262. TDLS_CMD_LINK_T rCmdLink;
  3263. /* sanity check */
  3264. if (peer == NULL) {
  3265. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: peer == NULL!\n", __func__);
  3266. return -EINVAL;
  3267. }
  3268. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: [%pM] %d %d\n",
  3269. __func__, peer, oper, (wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS));
  3270. if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
  3271. return -ENOTSUPP;
  3272. /* init */
  3273. prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy);
  3274. if (prGlueInfo == NULL) {
  3275. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo);
  3276. return -EINVAL;
  3277. }
  3278. prAdapter = prGlueInfo->prAdapter;
  3279. kalMemCopy(rCmdLink.aucPeerMac, peer, sizeof(rCmdLink.aucPeerMac));
  3280. rCmdLink.fgIsEnabled = FALSE;
  3281. /*
  3282. enum nl80211_tdls_operation {
  3283. NL80211_TDLS_DISCOVERY_REQ,
  3284. NL80211_TDLS_SETUP,
  3285. NL80211_TDLS_TEARDOWN,
  3286. NL80211_TDLS_ENABLE_LINK,
  3287. NL80211_TDLS_DISABLE_LINK,
  3288. };
  3289. */
  3290. switch (oper) {
  3291. case NL80211_TDLS_ENABLE_LINK:
  3292. rCmdLink.fgIsEnabled = TRUE;
  3293. break;
  3294. case NL80211_TDLS_DISABLE_LINK:
  3295. rCmdLink.fgIsEnabled = FALSE;
  3296. break;
  3297. case NL80211_TDLS_TEARDOWN:
  3298. case NL80211_TDLS_SETUP:
  3299. case NL80211_TDLS_DISCOVERY_REQ:
  3300. /* we do not support setup/teardown/discovery from driver */
  3301. return -ENOTSUPP;
  3302. default:
  3303. return -ENOTSUPP;
  3304. }
  3305. /* enable or disable TDLS link */
  3306. rStatus = kalIoctl(prGlueInfo,
  3307. TdlsexLinkCtrl, &rCmdLink, sizeof(TDLS_CMD_LINK_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
  3308. if (rStatus != WLAN_STATUS_SUCCESS) {
  3309. DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus);
  3310. return -EINVAL;
  3311. }
  3312. return 0;
  3313. }
  3314. /*----------------------------------------------------------------------------*/
  3315. /*! \brief This routine is called to send a command to TDLS module.
  3316. *
  3317. * \param[in] prGlueInfo Pointer to the Adapter structure
  3318. * \param[in] prInBuf A pointer to the command string buffer
  3319. * \param[in] u4InBufLen The length of the buffer
  3320. * \param[out] None
  3321. *
  3322. * \retval None
  3323. */
  3324. /*----------------------------------------------------------------------------*/
  3325. VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen)
  3326. {
  3327. UINT_32 u4Subcmd;
  3328. static void (*TdlsCmdTestFunc)(P_GLUE_INFO_T, UINT_8 *, UINT_32);
  3329. /* parse TDLS sub-command */
  3330. u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
  3331. DBGLOG(TDLS, INFO, "<tdls_cmd> sub command = %u\n", (UINT32) u4Subcmd);
  3332. TdlsCmdTestFunc = NULL;
  3333. /* handle different sub-command */
  3334. switch (u4Subcmd) {
  3335. #if TDLS_CFG_CMD_TEST /* only for unit test */
  3336. case TDLS_CMD_TEST_TX_FRAME:
  3337. /* simulate to send a TDLS frame */
  3338. /* TdlsCmdTestTxFrame(prGlueInfo, prInBuf, u4InBufLen); */
  3339. TdlsCmdTestFunc = TdlsCmdTestTxFrame;
  3340. break;
  3341. case TDLS_CMD_TEST_TX_TDLS_FRAME:
  3342. /* simulate to send a TDLS frame from supplicant */
  3343. /* TdlsCmdTestTxTdlsFrame(prGlueInfo, prInBuf, u4InBufLen); */
  3344. TdlsCmdTestFunc = TdlsCmdTestTxTdlsFrame;
  3345. break;
  3346. case TDLS_CMD_TEST_RCV_FRAME:
  3347. /* simulate to receive a TDLS frame */
  3348. /* TdlsCmdTestRvFrame(prGlueInfo, prInBuf, u4InBufLen); */
  3349. TdlsCmdTestFunc = TdlsCmdTestRvFrame;
  3350. break;
  3351. case TDLS_CMD_TEST_PEER_ADD:
  3352. /* simulate to add a TDLS peer */
  3353. /* TdlsCmdTestAddPeer(prGlueInfo, prInBuf, u4InBufLen); */
  3354. TdlsCmdTestFunc = TdlsCmdTestAddPeer;
  3355. break;
  3356. case TDLS_CMD_TEST_PEER_UPDATE:
  3357. /* simulate to update a TDLS peer */
  3358. /* TdlsCmdTestUpdatePeer(prGlueInfo, prInBuf, u4InBufLen); */
  3359. TdlsCmdTestFunc = TdlsCmdTestUpdatePeer;
  3360. break;
  3361. case TDLS_CMD_TEST_DATA_FRAME:
  3362. /* simulate to send a data frame to the peer */
  3363. /* TdlsCmdTestDataSend(prGlueInfo, prInBuf, u4InBufLen); */
  3364. TdlsCmdTestFunc = TdlsCmdTestDataSend;
  3365. break;
  3366. case TDLS_CMD_TEST_RCV_NULL:
  3367. /* simulate to receive a QoS null frame from the peer */
  3368. /* TdlsCmdTestNullRecv(prGlueInfo, prInBuf, u4InBufLen); */
  3369. TdlsCmdTestFunc = TdlsCmdTestNullRecv;
  3370. break;
  3371. case TDLS_CMD_TEST_SKIP_TX_FAIL:
  3372. /* command firmware to skip tx fail case */
  3373. /* TdlsCmdTestTxFailSkip(prGlueInfo, prInBuf, u4InBufLen); */
  3374. TdlsCmdTestFunc = TdlsCmdTestTxFailSkip;
  3375. break;
  3376. case TDLS_CMD_TEST_SKIP_KEEP_ALIVE:
  3377. /* command firmware to skip keep alive function */
  3378. /* TdlsCmdTestKeepAliveSkip(prGlueInfo, prInBuf, u4InBufLen); */
  3379. TdlsCmdTestFunc = TdlsCmdTestKeepAliveSkip;
  3380. break;
  3381. case TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT:
  3382. /* command firmware to skip channel switch timeout function */
  3383. /* TdlsCmdTestChSwTimeoutSkip(prGlueInfo, prInBuf, u4InBufLen); */
  3384. TdlsCmdTestFunc = TdlsCmdTestChSwTimeoutSkip;
  3385. break;
  3386. case TDLS_CMD_TEST_PROHIBIT_SET_IN_AP:
  3387. /* simulate to set Prohibited Bit in AP */
  3388. /* TdlsCmdTestProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */
  3389. TdlsCmdTestFunc = TdlsCmdTestProhibitedBitSet;
  3390. break;
  3391. case TDLS_CMD_TEST_SCAN_DISABLE:
  3392. /* command to disable scan request to do channel switch */
  3393. /* TdlsCmdTestScanCtrl(prGlueInfo, prInBuf, u4InBufLen); */
  3394. TdlsCmdTestFunc = TdlsCmdTestScanCtrl;
  3395. break;
  3396. case TDLS_CMD_TEST_DATA_FRAME_CONT:
  3397. /* simulate to send a data frame to the peer periodically */
  3398. /* TdlsCmdTestDataContSend(prGlueInfo, prInBuf, u4InBufLen); */
  3399. TdlsCmdTestFunc = TdlsCmdTestDataContSend;
  3400. break;
  3401. case TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP:
  3402. /* simulate to set channel switch Prohibited Bit in AP */
  3403. /* TdlsCmdTestChSwProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */
  3404. TdlsCmdTestFunc = TdlsCmdTestChSwProhibitedBitSet;
  3405. break;
  3406. case TDLS_CMD_TEST_DELAY:
  3407. /* delay a where */
  3408. /* TdlsCmdTestDelay(prGlueInfo, prInBuf, u4InBufLen); */
  3409. TdlsCmdTestFunc = TdlsCmdTestDelay;
  3410. break;
  3411. case TDLS_CMD_TEST_PTI_TX_FAIL:
  3412. /* simulate the tx done fail for PTI */
  3413. /* TdlsCmdTestPtiTxDoneFail(prGlueInfo, prInBuf, u4InBufLen); */
  3414. TdlsCmdTestFunc = TdlsCmdTestPtiTxDoneFail;
  3415. break;
  3416. #endif /* TDLS_CFG_CMD_TEST */
  3417. case TDLS_CMD_MIB_UPDATE:
  3418. /* update MIB parameters */
  3419. /* TdlsCmdMibParamUpdate(prGlueInfo, prInBuf, u4InBufLen); */
  3420. TdlsCmdTestFunc = TdlsCmdMibParamUpdate;
  3421. break;
  3422. case TDLS_CMD_UAPSD_CONF:
  3423. /* config UAPSD parameters */
  3424. /* TdlsCmdUapsdConf(prGlueInfo, prInBuf, u4InBufLen); */
  3425. TdlsCmdTestFunc = TdlsCmdUapsdConf;
  3426. break;
  3427. case TDLS_CMD_CH_SW_CONF:
  3428. /* enable or disable or start or stop channel switch function */
  3429. /* TdlsCmdChSwConf(prGlueInfo, prInBuf, u4InBufLen); */
  3430. TdlsCmdTestFunc = TdlsCmdChSwConf;
  3431. break;
  3432. case TDLS_CMD_SETUP_CONF:
  3433. /* config setup parameters */
  3434. /* TdlsCmdSetupConf(prGlueInfo, prInBuf, u4InBufLen); */
  3435. TdlsCmdTestFunc = TdlsCmdSetupConf;
  3436. break;
  3437. case TDLS_CMD_INFO:
  3438. /* display all TDLS information */
  3439. /* TdlsCmdInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */
  3440. TdlsCmdTestFunc = TdlsCmdInfoDisplay;
  3441. break;
  3442. case TDLS_CMD_KEY_INFO:
  3443. /* display key information */
  3444. /* TdlsCmdKeyInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */
  3445. TdlsCmdTestFunc = TdlsCmdKeyInfoDisplay;
  3446. break;
  3447. default:
  3448. break;
  3449. }
  3450. if (TdlsCmdTestFunc != NULL)
  3451. TdlsCmdTestFunc(prGlueInfo, prInBuf, u4InBufLen);
  3452. }
  3453. /*----------------------------------------------------------------------------*/
  3454. /*! \brief This routine is called to record a disconnection event.
  3455. *
  3456. * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
  3457. * \param[in] fgIsTearDown TRUE: tear down
  3458. * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
  3459. * \param[in] fgIsFromUs TRUE: tear down is from us
  3460. * \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE)
  3461. *
  3462. * \retval none
  3463. *
  3464. */
  3465. /*----------------------------------------------------------------------------*/
  3466. VOID
  3467. TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo,
  3468. BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode)
  3469. {
  3470. /* sanity check */
  3471. if ((prGlueInfo == NULL) || (pucPeerMac == NULL))
  3472. return;
  3473. DBGLOG(TDLS, INFO,
  3474. "<tdls_evt> %s: Rcv a inform from %pM %d %d\n",
  3475. __func__, pucPeerMac, fgIsFromUs, u2ReasonCode);
  3476. /* record */
  3477. TdlsLinkHistoryRecord(prGlueInfo, fgIsTearDown, pucPeerMac, fgIsFromUs, u2ReasonCode, NULL);
  3478. }
  3479. /*----------------------------------------------------------------------------*/
  3480. /*! \brief This routine is called to send a command to TDLS module.
  3481. *
  3482. * \param[in] prGlueInfo Pointer to the Adapter structure
  3483. * \param[in] prInBuf A pointer to the command string buffer
  3484. * \param[in] u4InBufLen The length of the buffer
  3485. * \param[out] None
  3486. *
  3487. * \retval None
  3488. */
  3489. /*----------------------------------------------------------------------------*/
  3490. VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen)
  3491. {
  3492. UINT32 u4EventId;
  3493. /* sanity check */
  3494. if ((prGlueInfo == NULL) || (prInBuf == NULL))
  3495. return; /* shall not be here */
  3496. /* handle */
  3497. u4EventId = *(UINT32 *) prInBuf;
  3498. u4InBufLen -= 4;
  3499. DBGLOG(TDLS, INFO, "<tdls> %s: Rcv a event: %d\n", __func__, u4EventId);
  3500. switch (u4EventId) {
  3501. case TDLS_HOST_EVENT_TEAR_DOWN:
  3502. TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen);
  3503. break;
  3504. case TDLS_HOST_EVENT_TX_DONE:
  3505. TdlsEventTxDone(prGlueInfo, prInBuf + 4, u4InBufLen);
  3506. break;
  3507. case TDLS_HOST_EVENT_FME_STATUS:
  3508. TdlsEventFmeStatus(prGlueInfo, prInBuf + 4, u4InBufLen);
  3509. break;
  3510. case TDLS_HOST_EVENT_STATISTICS:
  3511. TdlsEventStatistics(prGlueInfo, prInBuf + 4, u4InBufLen);
  3512. break;
  3513. }
  3514. }
  3515. /*----------------------------------------------------------------------------*/
  3516. /*!
  3517. * @brief This function is used to initialize variables in TDLS.
  3518. *
  3519. * \param[in] prAdapter Pointer to the Adapter structure
  3520. *
  3521. * @return TDLS_STATUS_SUCCESS: do not set key and key infor. is queued
  3522. TDLS_STATUS_FAILURE: set key
  3523. */
  3524. /*----------------------------------------------------------------------------*/
  3525. TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey)
  3526. {
  3527. STA_RECORD_T *prStaRec;
  3528. /* sanity check */
  3529. if ((prAdapter == NULL) || (prNewKey == NULL))
  3530. return TDLS_STATUS_FAILURE;
  3531. /*
  3532. supplicant will set key before updating station & enabling the link so we need to
  3533. backup the key information and set key when link is enabled
  3534. */
  3535. prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prNewKey->arBSSID);
  3536. if ((prStaRec != NULL) && IS_TDLS_STA(prStaRec)) {
  3537. DBGLOG(TDLS, TRACE, "<tdls> %s: [%pM] queue key (len=%d) until link is enabled\n",
  3538. __func__, prNewKey->arBSSID, (UINT32) prNewKey->u4KeyLength);
  3539. if (prStaRec->ucStaState == STA_STATE_3) {
  3540. DBGLOG(TDLS, TRACE, "<tdls> %s: [%pM] tear down the link due to STA_STATE_3\n",
  3541. __func__, prNewKey->arBSSID);
  3542. /* re-key */
  3543. TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE,
  3544. prStaRec->aucMacAddr, TRUE,
  3545. TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL);
  3546. /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
  3547. cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler,
  3548. prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
  3549. TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC);
  3550. return TDLS_STATUS_SUCCESS;
  3551. }
  3552. /* backup the key */
  3553. kalMemCopy(&prStaRec->rTdlsKeyTemp, prNewKey, sizeof(prStaRec->rTdlsKeyTemp));
  3554. return TDLS_STATUS_SUCCESS;
  3555. }
  3556. return TDLS_STATUS_FAILURE;
  3557. }
  3558. /*----------------------------------------------------------------------------*/
  3559. /*!
  3560. * @brief This function is used to initialize variables in TDLS.
  3561. *
  3562. * \param[in] prAdapter Pointer to the Adapter structure
  3563. *
  3564. * @return (none)
  3565. */
  3566. /*----------------------------------------------------------------------------*/
  3567. VOID TdlsexInit(ADAPTER_T *prAdapter)
  3568. {
  3569. GLUE_INFO_T *prGlueInfo;
  3570. /* init */
  3571. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  3572. /* reset */
  3573. kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink));
  3574. }
  3575. /*----------------------------------------------------------------------------*/
  3576. /*!
  3577. * \brief This routine is called to get any peer is in power save.
  3578. *
  3579. * \param[in] prAdapter Pointer to the Adapter structure
  3580. *
  3581. * \retval TRUE (at least one peer is in power save)
  3582. */
  3583. /*----------------------------------------------------------------------------*/
  3584. BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter)
  3585. {
  3586. STA_RECORD_T *prStaRec;
  3587. UINT32 u4StaId, u4StartIdx;
  3588. for (u4StaId = 0, u4StartIdx = 0; u4StaId < CFG_STA_REC_NUM; u4StaId++) {
  3589. /* list all TDLS peers */
  3590. prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx);
  3591. if (prStaRec == NULL)
  3592. break;
  3593. if (prStaRec->fgIsInPS == TRUE) {
  3594. DBGLOG(TDLS, TRACE, "<tx> yes, at least one peer is in ps\n");
  3595. return TRUE;
  3596. }
  3597. }
  3598. return FALSE;
  3599. }
  3600. /*----------------------------------------------------------------------------*/
  3601. /*!
  3602. * \brief This routine is called to enable or disable a TDLS link.
  3603. *
  3604. * \param[in] prAdapter Pointer to the Adapter structure
  3605. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  3606. * \param[in] u4SetBufferLen The length of the set buffer
  3607. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  3608. * bytes read from the set buffer. If the call failed due to invalid length of
  3609. * the set buffer, returns the amount of storage needed.
  3610. *
  3611. * \retval TDLS_STATUS_xx
  3612. */
  3613. /*----------------------------------------------------------------------------*/
  3614. TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  3615. {
  3616. GLUE_INFO_T *prGlueInfo;
  3617. TDLS_CMD_LINK_T *prCmd;
  3618. BSS_INFO_T *prBssInfo;
  3619. STA_RECORD_T *prStaRec;
  3620. TDLS_LINK_HIS_OTHERS_T rHisOthers;
  3621. /* sanity check */
  3622. if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) {
  3623. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: sanity fail!\n", __func__);
  3624. return TDLS_STATUS_FAILURE;
  3625. }
  3626. /* init */
  3627. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  3628. *pu4SetInfoLen = sizeof(TDLS_CMD_LINK_T);
  3629. prCmd = (TDLS_CMD_LINK_T *) pvSetBuffer;
  3630. /* search old entry */
  3631. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac);
  3632. if (prStaRec == NULL) {
  3633. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: cannot find the peer! %pM\n",
  3634. __func__, prCmd->aucPeerMac);
  3635. return TDLS_STATUS_FAILURE;
  3636. }
  3637. if (prCmd->fgIsEnabled == TRUE) {
  3638. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
  3639. DBGLOG(TDLS, TRACE, "<tdls_cfg> %s: NL80211_TDLS_ENABLE_LINK\n", __func__);
  3640. /* update key information after cnmStaRecChangeState(STA_STATE_3) */
  3641. prStaRec->fgTdlsInSecurityMode = FALSE;
  3642. if (prStaRec->rTdlsKeyTemp.u4Length > 0) {
  3643. UINT_32 u4BufLen; /* no use */
  3644. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: key len=%d\n",
  3645. __func__, (UINT32) prStaRec->rTdlsKeyTemp.u4Length);
  3646. /*
  3647. reminder the function that we are CIPHER_SUITE_CCMP,
  3648. do not change cipher type to CIPHER_SUITE_WEP128
  3649. */
  3650. _wlanoidSetAddKey(prAdapter, &prStaRec->rTdlsKeyTemp,
  3651. prStaRec->rTdlsKeyTemp.u4Length, FALSE, CIPHER_SUITE_CCMP, &u4BufLen);
  3652. /* clear the temp key */
  3653. prStaRec->fgTdlsInSecurityMode = TRUE;
  3654. kalMemZero(&prStaRec->rTdlsKeyTemp, sizeof(prStaRec->rTdlsKeyTemp));
  3655. }
  3656. /* check if we need to disable channel switch function */
  3657. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
  3658. if (prBssInfo->fgTdlsIsChSwProhibited == TRUE) {
  3659. TDLS_CMD_CORE_T rCmd;
  3660. kalMemZero(&rCmd, sizeof(TDLS_CMD_CORE_T));
  3661. rCmd.Content.rCmdChSwConf.ucNetTypeIndex = prStaRec->ucNetTypeIndex;
  3662. rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = FALSE;
  3663. kalMemCopy(rCmd.aucPeerMac, prStaRec->aucMacAddr, 6);
  3664. TdlsChSwConf(prAdapter, &rCmd, 0, 0);
  3665. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: disable channel switch\n", __func__);
  3666. }
  3667. TDLS_LINK_INCREASE(prGlueInfo);
  3668. /* record link */
  3669. if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N)
  3670. rHisOthers.fgIsHt = TRUE;
  3671. else
  3672. rHisOthers.fgIsHt = FALSE;
  3673. TdlsLinkHistoryRecord(prAdapter->prGlueInfo, FALSE,
  3674. prStaRec->aucMacAddr, !prStaRec->flgTdlsIsInitiator, 0, &rHisOthers);
  3675. } else {
  3676. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
  3677. cnmStaRecFree(prAdapter, prStaRec, TRUE); /* release to other TDLS peers */
  3678. DBGLOG(TDLS, TRACE, "<tdls_cfg> %s: NL80211_TDLS_DISABLE_LINK\n", __func__);
  3679. TDLS_LINK_DECREASE(prGlueInfo);
  3680. /* while(1); //sample debug */
  3681. }
  3682. /* work-around link count */
  3683. if ((TDLS_LINK_COUNT(prGlueInfo) < 0) || (TDLS_LINK_COUNT(prGlueInfo) > 1)) {
  3684. /* ERROR case: work-around to recount by searching all station records */
  3685. UINT32 u4Idx;
  3686. TDLS_LINK_COUNT_RESET(prGlueInfo);
  3687. for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) {
  3688. prStaRec = &prAdapter->arStaRec[u4Idx];
  3689. if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec))
  3690. TDLS_LINK_INCREASE(prGlueInfo);
  3691. }
  3692. if (TDLS_LINK_COUNT(prGlueInfo) > 1) {
  3693. /* number of links is still > 1 */
  3694. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: cTdlsLinkCnt %d > 1?\n",
  3695. __func__, TDLS_LINK_COUNT(prGlueInfo));
  3696. TDLS_LINK_COUNT_RESET(prGlueInfo);
  3697. /* free all TDLS links */
  3698. for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) {
  3699. prStaRec = &prAdapter->arStaRec[u4Idx];
  3700. if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec))
  3701. cnmStaRecFree(prAdapter, prStaRec, TRUE);
  3702. }
  3703. /* maybe inform supplicant ? */
  3704. }
  3705. }
  3706. /* display TDLS link history */
  3707. TdlsInfoDisplay(prAdapter, NULL, 0, NULL);
  3708. return TDLS_STATUS_SUCCESS;
  3709. }
  3710. /*----------------------------------------------------------------------------*/
  3711. /*!
  3712. * \brief This routine is called to send a TDLS action data frame.
  3713. *
  3714. * \param[in] prAdapter Pointer to the Adapter structure
  3715. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  3716. * \param[in] u4SetBufferLen The length of the set buffer
  3717. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  3718. * bytes read from the set buffer. If the call failed due to invalid length of
  3719. * the set buffer, returns the amount of storage needed.
  3720. *
  3721. * \retval TDLS_STATUS_xx
  3722. */
  3723. /*----------------------------------------------------------------------------*/
  3724. TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  3725. {
  3726. GLUE_INFO_T *prGlueInfo;
  3727. TDLS_MGMT_TX_INFO *prMgmtTxInfo;
  3728. STA_RECORD_T *prStaRec;
  3729. /* sanity check */
  3730. if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) {
  3731. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: sanity fail!\n", __func__);
  3732. return TDLS_STATUS_FAILURE;
  3733. }
  3734. /* init */
  3735. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  3736. *pu4SetInfoLen = sizeof(TDLS_MGMT_TX_INFO);
  3737. prMgmtTxInfo = (TDLS_MGMT_TX_INFO *) pvSetBuffer;
  3738. switch (prMgmtTxInfo->ucActionCode) {
  3739. case TDLS_FRM_ACTION_DISCOVERY_RESPONSE:
  3740. prStaRec = NULL;
  3741. break;
  3742. case TDLS_FRM_ACTION_SETUP_REQ:
  3743. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer);
  3744. if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3)) {
  3745. /* rekey? we reject re-setup link currently */
  3746. /* TODO: Still can setup link during rekey */
  3747. /*
  3748. return success to avoid supplicant clear TDLS entry;
  3749. Or we cannot send out any TDLS tear down frame to the peer
  3750. */
  3751. DBGLOG(TDLS, TRACE, "<tdls_cmd> %s: skip new setup on the exist link!\n", __func__);
  3752. return TDLS_STATUS_SUCCESS;
  3753. }
  3754. prStaRec = NULL;
  3755. break;
  3756. case TDLS_FRM_ACTION_SETUP_RSP:
  3757. case TDLS_FRM_ACTION_CONFIRM:
  3758. case TDLS_FRM_ACTION_TEARDOWN:
  3759. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer);
  3760. #if 0 /* in some cases, the prStaRec is still NULL */
  3761. /*
  3762. EX: if a peer sends us a TDLS setup request with wrong BSSID,
  3763. supplicant will not call TdlsexPeerAdd() to create prStaRec and
  3764. supplicant will send a TDLS setup response with status code 7.
  3765. So in the case, prStaRec will be NULL.
  3766. */
  3767. if (prStaRec == NULL) {
  3768. DBGLOG(TDLS, ERROR, "<tdls_cfg> %s: cannot find the peer!\n", __func__);
  3769. return -EINVAL;
  3770. }
  3771. #endif
  3772. break;
  3773. /*
  3774. TODO: Discovery response frame
  3775. Note that the TDLS Discovery Response frame is not a TDLS frame but a 11
  3776. Public Action frame.
  3777. In WiFi TDLS Tech Minutes June 8 2010.doc,
  3778. a public action frame (i.e. it is no longer an encapsulated data frame)
  3779. */
  3780. default:
  3781. DBGLOG(TDLS, ERROR,
  3782. "<tdls_cfg> %s: wrong action_code %d!\n", __func__, prMgmtTxInfo->ucActionCode);
  3783. return TDLS_STATUS_FAILURE;
  3784. }
  3785. /* send the TDLS data frame */
  3786. if (prStaRec != NULL) {
  3787. DBGLOG(TDLS, INFO, "<tdls_cfg> %s: [%pM] ps=%d status=%d\n",
  3788. __func__, prStaRec->aucMacAddr,
  3789. prStaRec->fgIsInPS, prMgmtTxInfo->u2StatusCode);
  3790. if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN) {
  3791. /* record disconnect history */
  3792. TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer,
  3793. TRUE, prMgmtTxInfo->u2StatusCode, NULL);
  3794. }
  3795. }
  3796. return TdlsDataFrameSend(prAdapter,
  3797. prStaRec,
  3798. prMgmtTxInfo->aucPeer,
  3799. prMgmtTxInfo->ucActionCode,
  3800. prMgmtTxInfo->ucDialogToken,
  3801. prMgmtTxInfo->u2StatusCode,
  3802. (UINT_8 *) prMgmtTxInfo->aucSecBuf, prMgmtTxInfo->u4SecBufLen);
  3803. }
  3804. /*----------------------------------------------------------------------------*/
  3805. /*!
  3806. * \brief This routine is called to add a peer record.
  3807. *
  3808. * \param[in] prAdapter Pointer to the Adapter structure
  3809. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  3810. * \param[in] u4SetBufferLen The length of the set buffer
  3811. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  3812. * bytes read from the set buffer. If the call failed due to invalid length of
  3813. * the set buffer, returns the amount of storage needed.
  3814. *
  3815. * \retval TDLS_STATUS_xx
  3816. */
  3817. /*----------------------------------------------------------------------------*/
  3818. TDLS_STATUS TdlsexPeerAdd(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  3819. {
  3820. GLUE_INFO_T *prGlueInfo;
  3821. TDLS_CMD_PEER_ADD_T *prCmd;
  3822. BSS_INFO_T *prAisBssInfo;
  3823. STA_RECORD_T *prStaRec;
  3824. UINT_8 ucNonHTPhyTypeSet;
  3825. UINT32 u4StartIdx;
  3826. OS_SYSTIME rCurTime;
  3827. /* sanity check */
  3828. DBGLOG(TDLS, INFO, "<tdls_cmd> %s\n", __func__);
  3829. if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) {
  3830. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: sanity fail!\n", __func__);
  3831. return TDLS_STATUS_FAILURE;
  3832. }
  3833. /* init */
  3834. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  3835. *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T);
  3836. prCmd = (TDLS_CMD_PEER_ADD_T *) pvSetBuffer;
  3837. prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  3838. u4StartIdx = 0;
  3839. /* search old entry */
  3840. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac);
  3841. /* check if any TDLS link exists because we only support one TDLS link currently */
  3842. if (prStaRec == NULL) {
  3843. /* the MAC is new peer */
  3844. prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx);
  3845. if (prStaRec != NULL) {
  3846. /* a building TDLS link exists */
  3847. DBGLOG(TDLS, ERROR,
  3848. "<tdls_cmd> %s: one TDLS link setup [%pM] is going...\n",
  3849. __func__, prStaRec->aucMacAddr);
  3850. if (prStaRec->ucStaState != STA_STATE_3) {
  3851. /* check timeout */
  3852. GET_CURRENT_SYSTIME(&rCurTime);
  3853. if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsSetupStartTime,
  3854. SEC_TO_SYSTIME(TDLS_SETUP_TIMEOUT_SEC))) {
  3855. /* free the StaRec */
  3856. cnmStaRecFree(prAdapter, prStaRec, TRUE);
  3857. DBGLOG(TDLS, ERROR,
  3858. "<tdls_cmd> %s: free going TDLS link setup [%pM]\n",
  3859. __func__, (prStaRec->aucMacAddr));
  3860. /* handle new setup */
  3861. prStaRec = NULL;
  3862. } else
  3863. return TDLS_STATUS_FAILURE;
  3864. } else {
  3865. /* the TDLS is built and works fine, reject new one */
  3866. return TDLS_STATUS_FAILURE;
  3867. }
  3868. }
  3869. } else {
  3870. if (prStaRec->ucStaState == STA_STATE_3) {
  3871. /* the peer exists, maybe TPK lifetime expired, supplicant wants to renew key */
  3872. TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE,
  3873. prStaRec->aucMacAddr, TRUE,
  3874. TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL);
  3875. /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
  3876. cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler,
  3877. prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
  3878. TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC);
  3879. DBGLOG(TDLS, TRACE,
  3880. "<tdls_cmd> %s: re-setup link for [%pM] maybe re-key?\n",
  3881. __func__, (prStaRec->aucMacAddr));
  3882. return TDLS_STATUS_FAILURE;
  3883. }
  3884. }
  3885. /*
  3886. create new entry if not exist
  3887. 1. we are initiator
  3888. (1) send TDLS setup request
  3889. wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
  3890. create a station record with STA_STATE_1.
  3891. (2) got TDLS setup response and send TDLS setup confirm
  3892. wpa_tdls_enable_link()
  3893. update a station record with STA_STATE_3.
  3894. 2. we are responder
  3895. (1) got TDLS setup request
  3896. wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
  3897. create a station record with STA_STATE_1.
  3898. (2) send TDLS setup response
  3899. (3) got TDLS setup confirm
  3900. wpa_tdls_enable_link()
  3901. update a station record with STA_STATE_3.
  3902. */
  3903. if (prStaRec == NULL) {
  3904. prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX);
  3905. if (prStaRec == NULL) {
  3906. /* shall not be here */
  3907. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: alloc prStaRec fail!\n", __func__);
  3908. return TDLS_STATUS_RESOURCES;
  3909. }
  3910. /* init the prStaRec */
  3911. /* prStaRec will be zero first in cnmStaRecAlloc() */
  3912. COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac);
  3913. /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); */
  3914. } else {
  3915. #if 0
  3916. if ((prStaRec->ucStaState > STA_STATE_1) && (IS_TDLS_STA(prStaRec))) {
  3917. /*
  3918. test plan: The STAUT should locally tear down existing TDLS direct link and
  3919. respond with Set up Response frame.
  3920. */
  3921. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
  3922. }
  3923. #endif
  3924. }
  3925. /* reference to bssCreateStaRecFromBssDesc() and use our best capability */
  3926. /* reference to assocBuildReAssocReqFrameCommonIEs() to fill elements */
  3927. /* prStaRec->u2CapInfo */
  3928. /* TODO: Need to parse elements from setup request frame */
  3929. prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet;
  3930. prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet;
  3931. prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet;
  3932. prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet;
  3933. prStaRec->eStaType = STA_TYPE_TDLS_PEER;
  3934. prStaRec->ucDesiredPhyTypeSet = /*prStaRec->ucPhyTypeSet & */
  3935. prAdapter->rWifiVar.ucAvailablePhyTypeSet;
  3936. ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG;
  3937. /* check for Target BSS's non HT Phy Types */
  3938. if (ucNonHTPhyTypeSet) {
  3939. if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) {
  3940. prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX;
  3941. } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) {
  3942. prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX;
  3943. } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */
  3944. prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
  3945. }
  3946. prStaRec->fgHasBasicPhyType = TRUE;
  3947. } else {
  3948. /* use mandatory for 11N only BSS */
  3949. /* ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); */
  3950. prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
  3951. prStaRec->fgHasBasicPhyType = FALSE;
  3952. }
  3953. /* update non HT Desired Rate Set */
  3954. {
  3955. P_CONNECTION_SETTINGS_T prConnSettings;
  3956. prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
  3957. prStaRec->u2DesiredNonHTRateSet =
  3958. (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet);
  3959. }
  3960. #if 0 /* TdlsexPeerAdd() will be called before we receive setup rsp in TdlsexRxFrameHandle() */
  3961. /* check if the add is from the same peer in the 1st unhandled setup request frame */
  3962. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: [%pM] [%pM]\n",
  3963. __func__, prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac);
  3964. if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) {
  3965. /* copy the HT capability from its setup request */
  3966. kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T));
  3967. prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N;
  3968. prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX);
  3969. /* reset backup */
  3970. kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap));
  3971. kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac));
  3972. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: peer is a HT device\n", __func__);
  3973. }
  3974. #endif
  3975. /* update WMM: must support due to UAPSD in TDLS link */
  3976. prStaRec->fgIsWmmSupported = TRUE;
  3977. prStaRec->fgIsUapsdSupported = TRUE;
  3978. /* update station record to firmware */
  3979. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
  3980. /* update time */
  3981. GET_CURRENT_SYSTIME(&prStaRec->rTdlsSetupStartTime);
  3982. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: create a peer [%pM]\n",
  3983. __func__, (prStaRec->aucMacAddr));
  3984. return TDLS_STATUS_SUCCESS;
  3985. }
  3986. /*----------------------------------------------------------------------------*/
  3987. /*!
  3988. * \brief This routine is called to update a peer record.
  3989. *
  3990. * \param[in] prAdapter Pointer to the Adapter structure
  3991. * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
  3992. * \param[in] u4SetBufferLen The length of the set buffer
  3993. * \param[out] pu4SetInfoLen If the call is successful, returns the number of
  3994. * bytes read from the set buffer. If the call failed due to invalid length of
  3995. * the set buffer, returns the amount of storage needed.
  3996. *
  3997. * \retval TDLS_STATUS_xx
  3998. */
  3999. /*----------------------------------------------------------------------------*/
  4000. TDLS_STATUS TdlsexPeerUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen)
  4001. {
  4002. GLUE_INFO_T *prGlueInfo;
  4003. TDLS_CMD_PEER_UPDATE_T *prCmd;
  4004. BSS_INFO_T *prAisBssInfo;
  4005. STA_RECORD_T *prStaRec;
  4006. IE_HT_CAP_T *prHtCap;
  4007. /* sanity check */
  4008. DBGLOG(TDLS, INFO, "<tdls_cmd> %s\n", __func__);
  4009. if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) {
  4010. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: sanity fail!\n", __func__);
  4011. return TDLS_STATUS_FAILURE;
  4012. }
  4013. /* init */
  4014. prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo;
  4015. *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T);
  4016. prCmd = (TDLS_CMD_PEER_UPDATE_T *) pvSetBuffer;
  4017. prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  4018. /* search old entry */
  4019. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac);
  4020. /*
  4021. create new entry if not exist
  4022. 1. we are initiator
  4023. (1) send TDLS setup request
  4024. wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
  4025. create a station record with STA_STATE_1.
  4026. (2) got TDLS setup response and send TDLS setup confirm
  4027. wpa_tdls_enable_link()
  4028. update a station record with STA_STATE_3.
  4029. 2. we are responder
  4030. (1) got TDLS setup request
  4031. wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
  4032. create a station record with STA_STATE_1.
  4033. (2) send TDLS setup response
  4034. (3) got TDLS setup confirm
  4035. wpa_tdls_enable_link()
  4036. update a station record with STA_STATE_3.
  4037. */
  4038. if ((prStaRec == NULL) || (prStaRec->fgIsInUse == 0)) {
  4039. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: cannot find the peer!\n", __func__);
  4040. return TDLS_STATUS_FAILURE;
  4041. }
  4042. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: update a peer [%pM] %d -> %d, 0x%x\n",
  4043. __func__, (prStaRec->aucMacAddr),
  4044. prStaRec->ucStaState, STA_STATE_3, prStaRec->eStaType);
  4045. if (!IS_TDLS_STA(prStaRec)) {
  4046. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: peer is not TDLS one!\n", __func__);
  4047. return TDLS_STATUS_FAILURE;
  4048. }
  4049. /* check if the add is from the same peer in the 1st unhandled setup request frame */
  4050. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: [%pM] [%pM]\n",
  4051. __func__, (prGlueInfo->aucTdlsHtPeerMac), (prCmd->aucPeerMac));
  4052. if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) {
  4053. /* copy the HT capability from its setup request */
  4054. kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T));
  4055. prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N;
  4056. prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX);
  4057. /* reset backup */
  4058. kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap));
  4059. kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac));
  4060. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: peer is a HT device\n", __func__);
  4061. }
  4062. /* update the record join time. */
  4063. GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime);
  4064. /* update Station Record - Status/Reason Code */
  4065. prStaRec->u2StatusCode = prCmd->u2StatusCode;
  4066. /* prStaRec->ucStaState shall be STA_STATE_1 */
  4067. prStaRec->u2CapInfo = prCmd->u2Capability;
  4068. /* prStaRec->u2OperationalRateSet */
  4069. prStaRec->u2AssocId = 0; /* no use */
  4070. prStaRec->u2ListenInterval = 0; /* unknown */
  4071. /* prStaRec->ucDesiredPhyTypeSet */
  4072. /* prStaRec->u2DesiredNonHTRateSet */
  4073. /* prStaRec->u2BSSBasicRateSet */
  4074. /* prStaRec->ucMcsSet */
  4075. /* prStaRec->fgSupMcs32 */
  4076. /* prStaRec->u2HtCapInfo */
  4077. prStaRec->fgIsQoS = TRUE;
  4078. prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE;
  4079. /* prStaRec->ucAmpduParam */
  4080. /* prStaRec->u2HtExtendedCap */
  4081. prStaRec->u4TxBeamformingCap = 0; /* no use */
  4082. prStaRec->ucAselCap = 0; /* no use */
  4083. prStaRec->ucRCPI = 0;
  4084. prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap;
  4085. prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap;
  4086. prStaRec->ucUapsdSp = prCmd->UapsdMaxSp;
  4087. /* update HT */
  4088. #if (TDLS_CFG_HT_SUP == 1)
  4089. if (prCmd->fgIsSupHt == FALSE) {
  4090. /* no HT IE is from supplicant so we use the backup */
  4091. prHtCap = (IE_HT_CAP_T *) &prStaRec->rTdlsHtCap;
  4092. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: [%pM] update ht ie 0x%x\n",
  4093. __func__, (prStaRec->aucMacAddr), prHtCap->ucId);
  4094. if (prHtCap->ucId == ELEM_ID_HT_CAP) {
  4095. prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0];
  4096. prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE;
  4097. prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo;
  4098. prStaRec->ucAmpduParam = prHtCap->ucAmpduParam;
  4099. prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap;
  4100. prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap;
  4101. prStaRec->ucAselCap = prHtCap->ucAselCap;
  4102. prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_SET_802_11N;
  4103. }
  4104. } else {
  4105. /* TODO: use the HT IE from supplicant */
  4106. }
  4107. #endif /* TDLS_CFG_HT_SUP */
  4108. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: UAPSD 0x%x %d MCS=0x%x\n",
  4109. __func__, prCmd->UapsdBitmap, prCmd->UapsdMaxSp, prStaRec->ucMcsSet);
  4110. /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */
  4111. DBGLOG(TDLS, INFO, "<tdls_cmd> %s: update a peer [%pM]\n",
  4112. __func__, (prStaRec->aucMacAddr));
  4113. return TDLS_STATUS_SUCCESS;
  4114. }
  4115. /*----------------------------------------------------------------------------*/
  4116. /*!
  4117. * \brief This routine is called to check if we need to drop a TDLS action frame.
  4118. *
  4119. * \param[in] *pPkt Pointer to the struct sk_buff->data.
  4120. * \param[in]
  4121. * \param[in]
  4122. *
  4123. * \retval None
  4124. */
  4125. /*----------------------------------------------------------------------------*/
  4126. BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, UINT_8 *pPkt)
  4127. {
  4128. ADAPTER_T *prAdapter;
  4129. UINT8 ucActionId;
  4130. /* sanity check */
  4131. if ((pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d))
  4132. return FALSE; /* not TDLS data frame htons(0x890d) */
  4133. #if 0 /* supplicant handles this check */
  4134. if (prStaRec == NULL)
  4135. return FALSE; /* shall not be here */
  4136. DBGLOG(TDLS, INFO,
  4137. "<tdls_fme> %s: Rcv a TDLS action frame (id=%d) %d %d\n",
  4138. __func__, *(pPkt + 13 + 4), prStaRec->fgTdlsIsProhibited, fgIsPtiTimeoutSkip);
  4139. /* check if TDLS Prohibited bit is set in AP's beacon */
  4140. if (prStaRec->fgTdlsIsProhibited == TRUE)
  4141. return TRUE;
  4142. #endif
  4143. ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */
  4144. if (fgIsPtiTimeoutSkip == TRUE) {
  4145. /* also skip any tear down frame from the peer */
  4146. if (ucActionId == TDLS_FRM_ACTION_TEARDOWN)
  4147. return TRUE;
  4148. }
  4149. prAdapter = prGlueInfo->prAdapter;
  4150. DBGLOG(TDLS, INFO,
  4151. "<tdls_fme> %s: Rcv a TDLS action frame %d (%u)\n",
  4152. __func__, ucActionId, (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem);
  4153. if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) {
  4154. DBGLOG(TDLS, WARN, "<tdls_fme> %s: Rcv a TDLS tear down frame %d, will DISABLE link\n",
  4155. __func__, *(pPkt + 13 + 4)); /* reason code */
  4156. /* record disconnect history */
  4157. TdlsLinkHistoryRecord(prGlueInfo, TRUE, pPkt + 6, FALSE, *(pPkt + 13 + 4), NULL);
  4158. /* inform tear down to supplicant only in OPEN/NONE mode */
  4159. /*
  4160. we need to tear down the link manually; or supplicant will display
  4161. "No FTIE in TDLS Teardown" and it will not tear down the link
  4162. */
  4163. cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
  4164. pPkt + 6, TDLS_FRM_ACTION_TEARDOWN, *(pPkt + 13 + 4), GFP_ATOMIC);
  4165. }
  4166. #if 0 /* pass all to supplicant except same thing is handled in supplicant */
  4167. if (((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI) ||
  4168. ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_REQ) ||
  4169. ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_RSP) ||
  4170. ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI_RSP)) {
  4171. return TRUE;
  4172. }
  4173. #endif
  4174. return FALSE;
  4175. }
  4176. /*----------------------------------------------------------------------------*/
  4177. /*! \brief This routine is called to parse some IEs in the setup frame from the peer.
  4178. *
  4179. * \param[in] prGlueInfo Pointer to the Adapter structure
  4180. * \param[in] pPkt Pointer to the ethernet packet
  4181. *
  4182. * \retval None
  4183. *
  4184. */
  4185. /*----------------------------------------------------------------------------*/
  4186. VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, UINT8 *pPkt, UINT16 u2PktLen)
  4187. {
  4188. ADAPTER_T *prAdapter;
  4189. STA_RECORD_T *prStaRec;
  4190. UINT8 ucActionId;
  4191. UINT8 *pucPeerMac, ucElmId, ucElmLen;
  4192. INT16 s2FmeLen;
  4193. /* sanity check */
  4194. if ((prGlueInfo == NULL) || (pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d))
  4195. return;
  4196. ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */
  4197. if ((ucActionId != TDLS_FRM_ACTION_SETUP_REQ) && (ucActionId != TDLS_FRM_ACTION_SETUP_RSP))
  4198. return;
  4199. /* init */
  4200. prAdapter = prGlueInfo->prAdapter;
  4201. pucPeerMac = pPkt + 6;
  4202. s2FmeLen = (INT16) u2PktLen;
  4203. DBGLOG(TDLS, TRACE,
  4204. "<tdls_fme> %s: get a setup frame %d from %pM\n",
  4205. __func__, ucActionId, (pucPeerMac));
  4206. if (ucActionId == TDLS_FRM_ACTION_SETUP_REQ)
  4207. pPkt += 12 + 2 + 2 + 1 + 1 + 2; /* skip action, dialog token, capability */
  4208. else
  4209. pPkt += 12 + 2 + 2 + 1 + 2 + 1 + 2; /* skip action, status code, dialog token, capability */
  4210. /* check station record */
  4211. prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, pucPeerMac);
  4212. if (prStaRec == NULL) {
  4213. prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX);
  4214. if (prStaRec == NULL) {
  4215. /* TODO: only one TDLS entry, need to free old one if timeout */
  4216. DBGLOG(TDLS, ERROR, "<tdls_cmd> %s: alloc prStaRec fail!\n", __func__);
  4217. return;
  4218. }
  4219. /* init the prStaRec */
  4220. /* prStaRec will be zero first in cnmStaRecAlloc() */
  4221. COPY_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMac);
  4222. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
  4223. }
  4224. /* backup HT IE to station record */
  4225. /* TODO: Maybe our TDLS only supports non-11n */
  4226. while (s2FmeLen > 0) {
  4227. ucElmId = *pPkt++;
  4228. ucElmLen = *pPkt++;
  4229. switch (ucElmId) {
  4230. case ELEM_ID_HT_CAP: /* 0x2d */
  4231. /* backup the HT IE of 1st unhandled setup request frame */
  4232. if (prGlueInfo->rTdlsHtCap.ucId == 0x00 &&
  4233. ucElmLen <= sizeof(IE_HT_CAP_T) - 2) {
  4234. kalMemCopy(prGlueInfo->aucTdlsHtPeerMac, pucPeerMac, 6);
  4235. kalMemCopy(&prGlueInfo->rTdlsHtCap, pPkt - 2, ucElmLen + 2);
  4236. /*
  4237. cannot backup in prStaRec; or
  4238. 1. we build a TDLS link
  4239. 2. peer re-sends setup req
  4240. 3. we backup HT cap element
  4241. 4. supplicant disables the link
  4242. 5. we clear the prStaRec
  4243. */
  4244. DBGLOG(TDLS, TRACE,
  4245. "<tdls_fme> %s: %pM: find a HT IE\n",
  4246. __func__, (pucPeerMac));
  4247. }
  4248. return;
  4249. case ELEM_ID_EXTENDED_CAP:
  4250. /* TODO: backup the extended capability IE */
  4251. break;
  4252. }
  4253. pPkt += ucElmLen;
  4254. s2FmeLen -= (2 + ucElmLen);
  4255. }
  4256. }
  4257. /*----------------------------------------------------------------------------*/
  4258. /*! \brief This routine is called to get the TDLS station record.
  4259. *
  4260. * \param[in] prGlueInfo Pointer to the Adapter structure
  4261. * \param[in] prInBuf A pointer to the command string buffer
  4262. * \param[in] u4InBufLen The length of the buffer
  4263. * \param[out] None
  4264. *
  4265. * \retval TDLS_STATUS_SUCCESS: this is TDLS packet
  4266. * TDLS_STATUS_FAILURE: this is not TDLS packet
  4267. */
  4268. /*----------------------------------------------------------------------------*/
  4269. TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo)
  4270. {
  4271. BSS_INFO_T *prBssInfo;
  4272. STA_RECORD_T *prStaRec;
  4273. TDLS_STATUS Status;
  4274. /* sanity check */
  4275. if ((prAdapter == NULL) || (prMsduInfo == NULL))
  4276. return TDLS_STATUS_FAILURE;
  4277. if (prAdapter->prGlueInfo == NULL)
  4278. return TDLS_STATUS_FAILURE;
  4279. if (TDLS_IS_NO_LINK_GOING(prAdapter->prGlueInfo))
  4280. return TDLS_STATUS_FAILURE;
  4281. /* init */
  4282. prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
  4283. Status = TDLS_STATUS_SUCCESS;
  4284. /* get record by ether dest */
  4285. prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMsduInfo->aucEthDestAddr);
  4286. /*
  4287. TDLS Setup Request frames, TDLS Setup Response frames and TDLS Setup Confirm
  4288. frames shall be transmitted through the AP and shall not be transmitted to a group
  4289. address.
  4290. 1. In first time, prStaRec == NULL or prStaRec->ucStaState != STA_STATE_3,
  4291. we will send them to AP;
  4292. 2. When link is still on, if you command to send TDLS setup from supplicant,
  4293. supplicant will DISABLE LINK first, prStaRec will be NULL then send TDLS
  4294. setup frame to the peer.
  4295. */
  4296. do {
  4297. if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3) && (IS_TDLS_STA(prStaRec))) {
  4298. /*
  4299. TDLS Test Case 5.3 Tear Down
  4300. Automatically sends TDLS Teardown frame to STA 2 via AP
  4301. 11.21.5 TDLS Direct Link Teardown
  4302. The TDLS Teardown frame shall be sent over the direct path and the reason
  4303. code shall be set to "TDLS 40 direct link teardown for unspecified reason",
  4304. except when the TDLS peer STA is unreachable via the TDLS direct link,
  4305. in which case, the TDLS Teardown frame shall be sent through the AP and
  4306. the reason code shall be set to "TDLS direct link teardown due to TDLS peer
  4307. STA unreachable via the TDLS direct link".
  4308. */
  4309. /* if (prStaRec->fgIsInPS == TRUE) */
  4310. /*
  4311. check if the packet is tear down:
  4312. we do not want to use PTI to indicate the tear down and
  4313. we want to send the tear down to AP then AP help us to send it
  4314. */
  4315. struct sk_buff *prSkb;
  4316. UINT8 *pEth;
  4317. UINT_16 u2EtherTypeLen;
  4318. prSkb = (struct sk_buff *)prMsduInfo->prPacket;
  4319. if (prSkb != NULL) {
  4320. UINT8 ucActionCode, ucReasonCode;
  4321. /* init */
  4322. pEth = prSkb->data;
  4323. u2EtherTypeLen = (pEth[ETH_TYPE_LEN_OFFSET] << 8) |
  4324. (pEth[ETH_TYPE_LEN_OFFSET + 1]);
  4325. ucActionCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 3];
  4326. ucReasonCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] |
  4327. (pEth[ETH_TYPE_LEN_OFFSET + 1 + 5] << 8);
  4328. /* TDLS_REASON_CODE_UNREACHABLE: keep alive fail or PTI timeout */
  4329. if ((u2EtherTypeLen == TDLS_FRM_PROT_TYPE) &&
  4330. (ucActionCode == TDLS_FRM_ACTION_TEARDOWN) &&
  4331. (ucReasonCode == TDLS_REASON_CODE_UNREACHABLE)) {
  4332. /*
  4333. when we cannot reach the peer,
  4334. we need AP's help to send the tear down frame
  4335. */
  4336. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  4337. prStaRec = prBssInfo->prStaRecOfAP;
  4338. if (prStaRec == NULL) {
  4339. Status = TDLS_STATUS_FAILURE;
  4340. break;
  4341. }
  4342. #if 0
  4343. /* change status code */
  4344. pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] = TDLS_REASON_CODE_UNREACHABLE;
  4345. #endif
  4346. }
  4347. }
  4348. prMsduInfo->ucStaRecIndex = prStaRec->ucIndex;
  4349. }
  4350. } while (FALSE);
  4351. DBGLOG(TDLS, INFO, "<tdls> %s: (Status=%x) [%pM] ucStaRecIndex = %d!\n",
  4352. __func__, (INT32) Status, (prMsduInfo->aucEthDestAddr),
  4353. prMsduInfo->ucStaRecIndex);
  4354. return Status;
  4355. }
  4356. /*----------------------------------------------------------------------------*/
  4357. /*!
  4358. * @brief This function is used to check if we suffer timeout for TX quota empty case.
  4359. *
  4360. * \param[in] prAdapter Pointer to the Adapter structure
  4361. *
  4362. * @return (none)
  4363. */
  4364. /*----------------------------------------------------------------------------*/
  4365. VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota)
  4366. {
  4367. OS_SYSTIME rCurTime;
  4368. /* sanity check */
  4369. if (!IS_TDLS_STA(prStaRec))
  4370. return;
  4371. if (FreeQuota != 0) {
  4372. /* reset timeout */
  4373. prStaRec->rTdlsTxQuotaEmptyTime = 0;
  4374. return;
  4375. }
  4376. /* work-around: check if the no free quota case is too long */
  4377. GET_CURRENT_SYSTIME(&rCurTime);
  4378. if (prStaRec->rTdlsTxQuotaEmptyTime == 0) {
  4379. prStaRec->rTdlsTxQuotaEmptyTime = rCurTime;
  4380. } else {
  4381. if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsTxQuotaEmptyTime,
  4382. SEC_TO_SYSTIME(TDLS_TX_QUOTA_EMPTY_TIMEOUT))) {
  4383. /* tear down the link */
  4384. DBGLOG(TDLS, WARN,
  4385. "<tdls> %s: [%pM] TX quota empty timeout!\n",
  4386. __func__, (prStaRec->aucMacAddr));
  4387. /* record disconnect history */
  4388. TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr,
  4389. TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY, NULL);
  4390. /* inform tear down to supplicant only in OPEN/NONE mode */
  4391. /*
  4392. we need to tear down the link manually; or supplicant will display
  4393. "No FTIE in TDLS Teardown" and it will not tear down the link
  4394. */
  4395. cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
  4396. prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
  4397. TDLS_REASON_CODE_UNREACHABLE, GFP_ATOMIC);
  4398. }
  4399. }
  4400. }
  4401. /*----------------------------------------------------------------------------*/
  4402. /*!
  4403. * @brief This function is used to un-initialize variables in TDLS.
  4404. *
  4405. * \param[in] prAdapter Pointer to the Adapter structure
  4406. *
  4407. * @return (none)
  4408. */
  4409. /*----------------------------------------------------------------------------*/
  4410. VOID TdlsexUninit(ADAPTER_T *prAdapter)
  4411. {
  4412. #if TDLS_CFG_CMD_TEST
  4413. cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend);
  4414. #endif /* TDLS_CFG_CMD_TEST */
  4415. }
  4416. #endif /* CFG_SUPPORT_TDLS */
  4417. /* End of tdls.c */