tdls.c 177 KB

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